Golang中如何像gorilla/mux路由器那样匹配URL模式的字符串

Golang中如何像gorilla/mux路由器那样匹配URL模式的字符串 基本上我有这段代码:

package main

import (
	"github.com/gorilla/mux"
	[...]
)

func main(){
	[...]
	router := mux.NewRouter()

	router.HandleFunc("/", handler.ViewAllPosts).Methods(http.MethodGet)
	router.HandleFunc("/events", handler.ViewEvents).Methods(http.MethodGet)
	router.HandleFunc("/about", handler.ViewAbout).Methods(http.MethodGet)
	router.HandleFunc("/blog/{URLTitle}", handler.ViewPost).Methods(http.MethodGet)
	[...]
}

我想做类似这样的事情:

switch urlStringVar {
	case "/":
		fmt.Println("ViewAllPosts")
	case "/events":
		fmt.Println("ViewEvents")
	case "/about":
		fmt.Println("ViewAbout")
	case "/blog/{URLTitle}":
		fmt.Println("ViewPost")
}

细节(如果可能的话)是它必须与 “gorilla/mux” 的匹配方式完全相同,有没有办法实现这一点?或者你推荐其他什么选项?


更多关于Golang中如何像gorilla/mux路由器那样匹配URL模式的字符串的实战教程也可以访问 https://www.itying.com/category-94-b0.html

6 回复

@ Sibert

这个我能做到,我的问题在于通配符:

case "/blog/{URLTitle}":

更多关于Golang中如何像gorilla/mux路由器那样匹配URL模式的字符串的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Willy:

有什么方法可以实现这一点吗?或者你推荐其他什么选项?

对于单层结构来说,这很简单。我还没有测试过多层结构。但是你可以从这里获取一些提示

另一种选择是查看 julienschmidt/httprouter 的代码。它仅仅是一个路由器,并且代码行数比 gorilla/mux 少得多。可能更容易理解其中的关键部分。

查看 gorilla/mux 的代码。

// Copyright 2012 The Gorilla Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package mux

import (
	"bytes"
	"fmt"
	"net/http"
	"net/url"
	"regexp"
	"strconv"
	"strings"
)

type routeRegexpOptions struct {
	strictSlash    bool
	useEncodedPath bool
}

Willy:

这个我能做到,我的问题在于通配符:

你可以使用这个函数来提取URL路径中向下两级的部分(通配符)(在这个例子中)。这可能需要额外的代码才能完全实现功能。

func getpath(r *http.Request) (string, string) {
	path := strings.Split(r.URL.String(), "/")
	switch len(path) {
	case 2:
		return path[1], "", ""
	default:
		return "", "", ""
	}
}

伪代码:

path1, path2 = getpath(r)

switch levels {
	case path2='':
		Open page path1
	default:
		Open page "blog/" + path2
}

if page not exist open 404.html

这减少了条件判断的层级。

可以使用 gorilla/muxPathMatch 方法来实现与路由器相同的URL模式匹配。以下是一个示例:

package main

import (
	"fmt"
	"net/http"
	"github.com/gorilla/mux"
)

func main() {
	// 创建路由器并定义路由
	router := mux.NewRouter()
	router.Path("/").Methods(http.MethodGet)
	router.Path("/events").Methods(http.MethodGet)
	router.Path("/about").Methods(http.MethodGet)
	router.Path("/blog/{URLTitle}").Methods(http.MethodGet)

	// 要测试的URL路径
	testPaths := []string{
		"/",
		"/events",
		"/about",
		"/blog/my-first-post",
		"/blog/another-post",
		"/invalid",
	}

	// 匹配每个路径
	for _, path := range testPaths {
		var match mux.RouteMatch
		request, _ := http.NewRequest("GET", path, nil)
		
		if router.Match(request, &match) {
			routePath, _ := match.Route.GetPathTemplate()
			vars := match.Vars
			
			fmt.Printf("路径: %s\n", path)
			fmt.Printf("  匹配路由: %s\n", routePath)
			if len(vars) > 0 {
				fmt.Printf("  路径变量: %v\n", vars)
			}
			
			// 根据匹配的路由执行相应操作
			switch routePath {
			case "/":
				fmt.Println("  执行: ViewAllPosts")
			case "/events":
				fmt.Println("  执行: ViewEvents")
			case "/about":
				fmt.Println("  执行: ViewAbout")
			case "/blog/{URLTitle}":
				fmt.Println("  执行: ViewPost")
				fmt.Printf("  文章标题: %s\n", vars["URLTitle"])
			}
		} else {
			fmt.Printf("路径: %s - 未匹配任何路由\n", path)
		}
		fmt.Println()
	}
}

输出示例:

路径: /
  匹配路由: /
  执行: ViewAllPosts

路径: /events
  匹配路由: /events
  执行: ViewEvents

路径: /about
  匹配路由: /about
  执行: ViewAbout

路径: /blog/my-first-post
  匹配路由: /blog/{URLTitle}
  执行: ViewPost
  文章标题: my-first-post

路径: /blog/another-post
  匹配路由: /blog/{URLTitle}
  执行: ViewPost
  文章标题: another-post

路径: /invalid - 未匹配任何路由

如果需要更简洁的封装,可以创建一个匹配函数:

func matchPath(router *mux.Router, path string) (string, map[string]string, bool) {
	var match mux.RouteMatch
	request, _ := http.NewRequest("GET", path, nil)
	
	if router.Match(request, &match) {
		routePath, _ := match.Route.GetPathTemplate()
		return routePath, match.Vars, true
	}
	return "", nil, false
}

// 使用示例
func handleURL(path string) {
	router := mux.NewRouter()
	router.Path("/").Methods(http.MethodGet)
	router.Path("/events").Methods(http.MethodGet)
	router.Path("/about").Methods(http.MethodGet)
	router.Path("/blog/{URLTitle}").Methods(http.MethodGet)
	
	if routePath, vars, matched := matchPath(router, path); matched {
		switch routePath {
		case "/":
			fmt.Println("ViewAllPosts")
		case "/events":
			fmt.Println("ViewEvents")
		case "/about":
			fmt.Println("ViewAbout")
		case "/blog/{URLTitle}":
			fmt.Printf("ViewPost - Title: %s\n", vars["URLTitle"])
		}
	} else {
		fmt.Println("No match found")
	}
}

这种方法直接使用 gorilla/mux 的路由匹配引擎,确保与路由器本身的匹配行为完全一致。

回到顶部