You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

不借助框架实现Go路由参数匹配 需构建多少个路由处理器

结论

你可以根据实现需求灵活选择两种方案,最低仅需1个通用路由处理器,更易维护的写法是编写2个独立的业务路由处理器:

方案1:2个独立业务处理器(更推荐)

  • 先实现一个通用的路径参数解析工具,用来从URL路径中提取{tenderReference}和{venderCode}两个参数
  • 分别为两个业务路由编写独立的处理器函数,每个处理器内先调用参数解析工具拿到参数,初始化Tender结构体后调用对应的readWrite/readOnly方法
  • 最后把两个处理器绑定对应的路径规则注册到路由中即可

方案2:1个通用分发处理器(代码量更少)

  • 仅编写一个全局处理器,在处理器内先判断当前请求路径匹配哪个路由规则,提取参数后根据路径的操作类型(readWrite/readOnly)决定调用Tender的对应方法
  • 这种方式只需要1个处理器,但逻辑耦合度更高,后续新增路由时维护成本会上升

简单实现示例
import (
	"fmt"
	"net/http"
	"strconv"
	"strings"
)

type Tender struct {
	tenderReference string
	venderCode      int
}

func (t Tender) readWrite() {
	fmt.Printf("Tender %s is ready for vendor %d to review and submit\n", t.tenderReference, t.venderCode)
}

func (t Tender) readOnly(w http.ResponseWriter, r *http.Request) {
	fmt.Printf("Tender %s already submitted by vender %d\n", t.tenderReference, t.venderCode)
}

// 通用路径参数解析函数
func parseParams(pattern, path string) (map[string]string, bool) {
	patternParts := strings.Split(strings.Trim(pattern, "/"), "/")
	pathParts := strings.Split(strings.Trim(path, "/"), "/")
	if len(patternParts) != len(pathParts) {
		return nil, false
	}
	params := make(map[string]string)
	for i, part := range patternParts {
		if strings.HasPrefix(part, "{") && strings.HasSuffix(part, "}") {
			paramName := strings.TrimSuffix(strings.TrimPrefix(part, "{"), "}")
			params[paramName] = pathParts[i]
		} else if part != pathParts[i] {
			return nil, false
		}
	}
	return params, true
}

// 两个独立处理器实现
func readWriteHandler(w http.ResponseWriter, r *http.Request) {
	params, ok := parseParams("/api/tender/readWrite/{tenderReference}/vendor/{venderCode}", r.URL.Path)
	if !ok {
		http.NotFound(w, r)
		return
	}
	venderCode, err := strconv.Atoi(params["venderCode"])
	if err != nil {
		http.Error(w, "无效的供应商编码", http.StatusBadRequest)
		return
	}
	tender := Tender{
		tenderReference: params["tenderReference"],
		venderCode:      venderCode,
	}
	tender.readWrite()
	w.WriteHeader(http.StatusOK)
}

func readOnlyHandler(w http.ResponseWriter, r *http.Request) {
	params, ok := parseParams("/api/tender/readOnly/{tenderReference}/vendor/{venderCode}", r.URL.Path)
	if !ok {
		http.NotFound(w, r)
		return
	}
	venderCode, err := strconv.Atoi(params["venderCode"])
	if err != nil {
		http.Error(w, "无效的供应商编码", http.StatusBadRequest)
		return
	}
	tender := Tender{
		tenderReference: params["tenderReference"],
		venderCode:      venderCode,
	}
	tender.readOnly(w, r)
	w.WriteHeader(http.StatusOK)
}

// 注册路由启动服务
func main() {
	http.HandleFunc("/api/tender/readWrite/", readWriteHandler)
	http.HandleFunc("/api/tender/readOnly/", readOnlyHandler)
	http.ListenAndServe(":8080", nil)
}

内容的提问来源于stack exchange,提问作者Hasan A Yousef

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 16:54:03