Golang简化路由处理程序实现无框架参数处理

Golang简化路由处理程序实现无框架参数处理 在 rocket.rs 中,我们有这样简单的路由代码:

#[get("/hello/<name>/<age>")]
fn hello(name: &str, age: u8) -> String {
    format!("Hello, {} year old named {}!", age, name)
}

如果你在浏览器中访问 http://localhost:8000/hello/John/58,你会看到: Hello, 58 year old named John!

我读过 这个,但被采纳的 答案 是关于为单个路由实现 Go url 参数映射 的方法,该方法可以将 http://localhost:8080/blob/123/test 解析为 /blob/{id}/test 并显示所需的路由。

我知道那里有一些很棒的路由器/框架,但我希望自己构建简单的代码,以便更好地理解 HTTP 路由处理器。

假设我有:

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)
}

并且希望我的路由类似于:

  1. /api/tender/readWrite/{tenderReference}/vendor/{venderCode} 调用 func (t Tender) readWrite(){}
  2. /api/tender/readOnly/{tenderReference}/vendor/{venderCode} 调用 func (t Tender) readOnly(){}

我需要构建多少个路由处理器?


更多关于Golang简化路由处理程序实现无框架参数处理的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang简化路由处理程序实现无框架参数处理的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go中实现无框架参数处理,你可以使用net/http的标准库配合自定义路由解析。对于你的需求,需要构建两个路由处理器,但可以通过一个通用的处理器函数来动态处理不同的路径和方法。以下是示例代码:

package main

import (
    "fmt"
    "net/http"
    "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)
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("ReadOnly processed"))
}

func parseTenderPath(path string) (tenderReference string, venderCode int, action string, ok bool) {
    // 路径格式: /api/tender/{action}/{tenderReference}/vendor/{venderCode}
    parts := strings.Split(path, "/")
    if len(parts) != 7 {
        return "", 0, "", false
    }
    if parts[1] != "api" || parts[2] != "tender" || parts[5] != "vendor" {
        return "", 0, "", false
    }
    
    action = parts[3]
    tenderReference = parts[4]
    
    // 简单转换venderCode,实际使用时需添加错误处理
    fmt.Sscanf(parts[6], "%d", &venderCode)
    return tenderReference, venderCode, action, true
}

func tenderHandler(w http.ResponseWriter, r *http.Request) {
    tenderRef, vendorCode, action, ok := parseTenderPath(r.URL.Path)
    if !ok {
        http.NotFound(w, r)
        return
    }
    
    t := Tender{
        tenderReference: tenderRef,
        venderCode:      vendorCode,
    }
    
    switch action {
    case "readWrite":
        t.readWrite()
        w.WriteHeader(http.StatusOK)
        w.Write([]byte("ReadWrite processed"))
    case "readOnly":
        t.readOnly(w, r)
    default:
        http.NotFound(w, r)
    }
}

func main() {
    http.HandleFunc("/api/tender/", tenderHandler)
    http.ListenAndServe(":8080", nil)
}

这个实现使用单个tenderHandler处理所有以/api/tender/开头的路由。parseTenderPath函数从URL路径中提取参数,然后根据action字段调用相应的方法。访问示例:

  • http://localhost:8080/api/tender/readWrite/REF123/vendor/456 调用readWrite
  • http://localhost:8080/api/tender/readOnly/REF789/vendor/101 调用readOnly

如果需要更灵活的路径匹配,可以考虑使用正则表达式:

import "regexp"

var tenderPathRegex = regexp.MustCompile(`^/api/tender/(readWrite|readOnly)/([^/]+)/vendor/(\d+)$`)

func parseTenderPathRegex(path string) (tenderReference string, venderCode int, action string, ok bool) {
    matches := tenderPathRegex.FindStringSubmatch(path)
    if matches == nil {
        return "", 0, "", false
    }
    
    action = matches[1]
    tenderReference = matches[2]
    fmt.Sscanf(matches[3], "%d", &venderCode)
    return tenderReference, venderCode, action, true
}

这种方法避免了依赖外部框架,同时保持了代码的简洁性和可维护性。

回到顶部