英文:
How does httprouterhttp.HandlerFunc() works?
问题
我正在学习Go语言,并且目前正在尝试理解julienschmidt的httprouter路由器的工作原理,特别是router.HandlerFunc()的工作原理。
Go的http包:
http.Handler
:Handler是一个接口。任何具有相同方法签名(即ServeHTTP(w, r))的类型都可以实现Handler接口。http.Handle
:http.Handle是一个函数,它有两个参数。1)用于匹配请求路径的字符串,2)Handler,用于调用其ServeHTTP()方法。http.HandlerFunc
:一个具有函数签名(ResponseWriter, *Request)和自己的ServeHTTP(w, r)方法的自定义函数类型,它满足http.Handler接口。
现在,如果我需要使用一个满足HandlerFunc的函数,比如Bar(ResponseWriter, *Request),在http.Handle中,我需要将该函数强制转换为http.HandlerFunc,然后在http.Handle中使用它,就像这样:
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的源代码,可以看到http.HandleFunc()的工作原理。它期望一个具有(w ResponseWriter, r *Request)签名的函数,并将该函数强制转换为HandlerFunc类型。
像这样:
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
if handler == nil {
panic("http: nil handler")
}
mux.Handle(pattern, HandlerFunc(handler))
}
julienschmidt的httprouter
func (r *Router) HandlerFunc(method, path string, handler http.HandlerFunc) {
r.Handler(method, path, handler)
}
- 与http.HandleFunc()不同,它不期望一个具有适当签名(ResponseWriter, *Request)的函数,而是期望一个http.HandlerFunc。
- 而且,它不需要将函数强制转换为HandlerFunc类型,只需将函数传递给另一个函数router.Handler(method, path string, handler http.Handler),该函数又期望一个Handler。
所以,我可以毫无问题地执行这段代码:
router.HandlerFunc(http.MethodPost, "/path", Bar) // Bar没有被强制转换为HandlerFunc
我可以理解将Bar强制转换为HandlerFunc,然后将其传递给router.HandlerFunc()。
请帮我解答一些疑问:
- 如果没有将Bar()强制转换为HandlerFunc,它如何满足router.HandlerFunc()的HandlerFunc类型?
- 如果router.Handler()期望一个http.Handler类型,那么没有将Bar()强制转换为http.HandlerFunc,它如何满足router.Handler()的Handler类型?
- 我漏掉了什么?
英文:
I am learning Go and at the moment trying to understand what and how actually julienschmidt's httprouterhttp router works. Especially how the router.HandlerFunc() works.
Go's http package:
http.Handler
: Handler is an Interface. Any type which has the same method signature i.e., ServeHTTP(w,r) implements a Handler.http.Handle
: http.Handle is a function which has two parameters. 1) String to match request path, 2)Handler, to call its ServeHTTP() method.http.HandlerFunc
: A custom function type with function signature (ResponseWriter, *Request) and its own ServeHTTP(w,r) method, which satisfies as a http.Handler interface.
Now if I need to use a function eg. Bar(ResponseWriter, *Request) which satisfies to be a HandlerFunc, inside http.Handle, I type caste/covert the function to http.HandlerFunc and then use it inside the http.Handle. Like so:
func Bar(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("My bar func response"))
}
...
mf := http.HandlerFunc(Bar)
http.Handle("/path", mf)
- Looking at the http.HandleFunc source code, this is how http.HandleFunc() works. It expects a function which as the signature of (w ResponseWriter, r *Request) and type caste the function.
Like so:
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
Looking at the source code of router.HandlerFunc()
func (r *Router) HandlerFunc(method, path string, handler http.HandlerFunc) {
r.Handler(method, path, handler)
}
- Instead of expecting a function with appropriate signature (ResponseWriter, *Request) like the http.HandleFunc(), it expects a http.HandlerFunc.
- Also without type casting/converting the function to a HandlerFunc type, it just pass the function to another function router.Handler(method, path string, handler http.Handler), which again expects a Handler.
So I can execute this code without any problem:
router.HandlerFunc(http.MethodPost, "/path", Bar) // Bar is not type casted/converted to a HandlerFunc
I can understand type casting the Bar to a HandlerFunc and then pass it to router.HandlerFunc().
Could you please clear some of my doubts:
- How does without type casting the Bar() to a HandlerFunc satisfies as a HandlerFunc type to the router.HandlerFunc()?
- 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()?
- What am I missing?
答案1
得分: 3
- 不需要将Bar()转换为HandlerFunc类型,它仍然可以满足作为HandlerFunc类型传递给router.HandlerFunc()的要求。
表达式
router.HandlerFunc(http.MethodPost, "/path", Bar)
符合可赋值性规则:
V
和T
具有相同的底层类型,并且V
或T
中至少有一个不是命名类型。
Bar函数的类型和http.HandlerFunc类型具有相同的底层类型,并且Bar的类型不是命名类型。因此,你可以将Bar作为handler参数传递(赋值)给httprouter.Router.HandlerFunc,而无需进行显式转换。
- 如果router.Handler()期望一个http.Handler类型,那么为什么Bar()不需要转换为http.HandlerFunc类型就可以满足作为handler传递给router.Handler()的要求?
在以下方法定义中
func (r *Router) HandlerFunc(method, path string, handler http.HandlerFunc) {
r.Handler(method, path, handler)
}
没有Bar
,只有类型为http.HandlerFunc
的handler
参数,而该类型实现了http.Handler
接口。因此,语句r.Handler(method, path, handler)
是完全合法的。
- 你可能忽略了上述内容。
英文:
- "How does without type casting the Bar() to a HandlerFunc satisfies as a HandlerFunc type to the router.HandlerFunc()?"
The expression
router.HandlerFunc(http.MethodPost, "/path", Bar)
complies with the rules of Assignability:
> V
and T
have identical underlying types and at least one of V
or T
is not a named type.
The Bar
function's type and the http.HandlerFunc
type have identical underlying types, and Bar
's type is not named. Because of that you can pass (assign) Bar
as the handler
argument to httprouter.Router.HandlerFunc
without an explicit conversion.
- "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()?"
In the following method definition
func (r *Router) HandlerFunc(method, path string, handler http.HandlerFunc) {
r.Handler(method, path, handler)
}
there is no Bar
, there's only the handler
argument whose type is http.HandlerFunc
and that type does implement the http.Handler
interface. So the statement r.Handler(method, path, handler)
is perfectly legitimate.
- "What am I missing?"
See above.
答案2
得分: 0
看一下HandlerFunc的定义:
type HandlerFunc func(ResponseWriter, *Request)
以及你的函数的签名:
(w http.ResponseWriter, r *http.Request)
这里不需要进行转换。
英文:
Look at definition of HandlerFunc
type HandlerFunc func(ResponseWriter, *Request)
And the signature of your function
(w http.ResponseWriter, r *http.Request)
You don't need conversion here.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论