我正在学习Go,目前正试图了解julienschmidt's httprouterhttp路由的实际工作原理和工作方式.尤其是路由.HandlerFunc()可以工作.

Go's http package:

  • http.Handler:处理程序是一个接口.任何具有相同方法签名的类型,即ServeHTTP(w,r)实现一个处理程序.
  • http.Handle:http.Handle是一个有两个参数的函数.1) 字符串匹配请求路径,2)处理程序,以调用其ServeHTTP()方法.
  • http.HandlerFunc:一种自定义函数类型,具有函数签名(ResponseWriter,*Request)和自己的ServeHTTP(w,r)方法,满足http.处理程序接口.

现在,如果我需要在http内使用一个满足HandlerFunc的函数,例如Bar(ResponseWriter,*Request).Handle,我键入caste/covert将函数转换为http.HandlerFunc,然后在http中使用它.手柄像这样:

func Bar(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("My bar func response"))
}
...
mf := http.HandlerFunc(Bar)
http.Handle("/path", mf)
  • 看看http.HandleFunc source code,这就是http.HandleFunc()起作用.它需要一个函数作为(w ResponseWriter,r*Request)的签名,并键入caste函数.

像这样:

func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    if handler == nil {
        panic("http: nil handler")
    }
    mux.Handle(pattern, HandlerFunc(handler))
}

julienschmidt's httprouterhttp

看看source code of router.HandlerFunc()

func (r *Router) HandlerFunc(method, path string, handler http.HandlerFunc) {
    r.Handler(method, path, handler)
}
  • 而不是像http那样期望具有适当签名(ResponseWriter,*Request)的函数.HandleFunc(),它需要http.HandlerFunc.
  • 也没有类型转换/将函数转换为HandlerFunc类型,它只是将函数传递给另一个函数路由.Handler(方法,路径字符串,Handler http.Handler),它再次需要一个处理程序.

因此,我可以毫无问题地执行此代码:

router.HandlerFunc(http.MethodPost, "/path", Bar) // Bar is not type casted/converted to a HandlerFunc

我可以理解将条类型转换为HandlerFunc,然后将其传递给router.HandlerFunc().

请你澄清我的一些疑问:

  1. 如果不将Bar()类型强制转换为HandlerFunc,如何满足路由的HandlerFunc类型.HandlerFunc()?
  2. 如果路由.Handler()需要http.处理程序类型,为什么Bar()没有对http进行类型转换.HandlerFunc满足路由的处理程序.Handler()?
  3. 我错过了什么?

推荐答案

  1. "How does without type casting the Bar() to a HandlerFunc satisfies as a HandlerFunc type to the router.HandlerFunc()?"

表达式

router.HandlerFunc(http.MethodPost, "/path", Bar)

符合Assignability条规则:

VT具有identical underlying types,并且VT中的至少一个为not a named型.

Bar函数的类型和http.HandlerFunc函数的类型为identical underlying typesBar函数的类型为not named.因此,您可以将Bar作为handler参数传递(赋值)给httprouter.Router.HandlerFunc,而不需要explicit conversion.


  1. "If the router.Handler() expects a http.Handler type, how come Bar() without type casting to the http.HandlerFunc satisfies a a Handler to the router.Handler()?"

在以下方法定义中

func (r *Router) HandlerFunc(method, path string, handler http.HandlerFunc) {
    r.Handler(method, path, handler)
}

no Bar,只有handler参数,其类型is http.HandlerFunc和类型does实现http.Handler接口.所以r.Handler(method, path, handler)号声明是完全合法的.


  1. "What am I missing?"

见上文.

Go相关问答推荐

Go 1.22 net/http群组路由

Kafka消费者在需要时不会暂停

Go GORM创建表,但不创建列

难以为多个平台添加Go Bazel构建选项

CGO Linux到Windows交叉编译中的未知类型名称

由于索引器压缩比限制,扫描包含golang包的图像时,伪影XRAY失败

显示GUI时后台处理功能

无法使用exec从管道中读取.Go中的命令

如何在 Chi Router 的受保护路由下提供静态文件(尤其是图像)?

Golang text/template中的startswith函数 - 入门教程

如何为ANTLR4目标Go调试监听器

Kubo,来自 IpfsNode.Bootstrap 的无效内存地址或零指针取消引用

类型/ struct 函数的 GoDoc 示例函数

如何使用 fyne Go 使用 canvas.NewText() 使文本可滚动

对所有标志进行 ORing 的简短方法

如何使用 math/big 对 bigInt 进行取模?

如何在gin中获取参数值数组

将未知长度切片的值分配给Go中的 struct ?

显示作为服务帐户身份验证的谷歌日历事件 - Golang App

如何在 Prometheus 中正确检测区域和环境信息?