英文:
Use function that accepts io.Writer as HandleFunc
问题
我想创建一个函数,可以作为http
的HandleFunc
,同时也可以使用另一个writer进行调用。
由于http.ResponseWriter
实现了io.Writer
,而且我的函数不需要设置HTTP头,所以我认为这可能是可能的:
func doit(w io.Writer, r *http.Request) {
w.Write([]byte("Hello"))
}
http.HandleFunc("/", doit)
但是不行:
cannot use doit (type func(io.Writer, *http.Request)) as type func(http.ResponseWriter, *http.Request) in argument to http.HandleFunc
这是有道理的,因为需要进行类型断言才能使io.Writer
与预期的http.ResponseWriter
兼容。
函数能否实现这样的功能呢?
英文:
I would like to make a function that can be a HandleFunc for http
but also be called with another writer.
Since http.ResponseWriter
implements io.Writer
and my function does not need to set HTTP headers, I thought it might be possible:
func doit(w io.Writer, r *http.Request) {
w.Write([]byte("Hello"))
}
http.HandleFunc("/", doit)
But no:
> cannot use doit (type func(io.Writer, *http.Request)) as type func(http.ResponseWriter, *http.Request) in argument to http.HandleFunc
That makes sense, because it would require a type assertion to make an io.Writer compatible with an expected http.ResponseWriter.
Is something like that possible with functions?
答案1
得分: 6
函数类型表示具有相同参数和结果类型的所有函数的集合。
你的 doit()
函数不符合 http.HandlerFunc
的要求,因为参数类型不匹配。io.Writer
和 http.ResponseWriter
是两种完全不同的类型,因此接受这些类型的函数类型也是不同的。
使用匿名函数值
然而,由于接口类型 io.Writer
的方法集是 http.ResponseWriter
的方法集的子集,所以可以将后者类型的值赋值给前者类型的变量。
你可以将其包装在类型为 http.HandlerFunc
的匿名函数中,该函数可以简单地调用 doit()
,然后你可以将其用作 http.HandlerFunc
:
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
doit(w, r)
})
带有辅助函数的匿名函数值
如果你需要多次使用,可以创建一个辅助函数来生成 http.HandlerFunc
函数值:
func wrap(f func(w io.Writer, r *http.Request)) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
f(w, r)
}
}
然后使用它非常简单:
http.HandleFunc("/", wrap(doit))
使用自定义的 Handler
类型
另一种选择是定义自己的函数类型,你可以附加一个简单的方法来实现 http.Handler
(即 ServeHTTP()
),这样通过简单的类型转换,你可以将函数注册为处理程序:
type SimpleHandler func(io.Writer, *http.Request)
func (sh SimpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
sh(w, r)
}
使用它:
http.Handle("/", SimpleHandler(doit))
请注意,表达式 SimpleHandler(doit)
只是一种类型转换,它不是函数调用。因此,在后台没有创建新值或匿名函数,这种解决方案是最高效的。
英文:
> A function type denotes the set of all functions with the same parameter and result types.
Your doit()
function does not qualify to be an http.HandlerFunc
because parameter types do not match. The types io.Writer
and http.ResponseWriter
are 2 completely different types, so the function types taking these types are also different.
Using an anonymous function value
However, since the method set of the interface type io.Writer
is a subset of the method set of http.ResponseWriter
, a value of the latter type can be assigned to the variable of the former type.
You may wrap it in an anonymous function of type http.HandlerFunc
which may simply call doit()
, and then you may use it as an http.HandlerFunc
:
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
doit(w, r)
})
Anonymous function value with helper function
If you need this many times, you may create a helper function to produce the http.HandlerFunc
function value:
func wrap(f func(w io.Writer, r *http.Request)) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
f(w, r)
}
}
And then using it is simply:
http.HandleFunc("/", wrap(doit))
With custom Handler
type
Another option would be to define your own function type, to which you can attach a simple method to implement http.Handler
(namely ServeHTTP()
), and that way with a simple type conversion you can register your function as a handler:
type SimpleHandler func(io.Writer, *http.Request)
func (sh SimpleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
sh(w, r)
}
Using it:
http.Handle("/", SimpleHandler(doit))
Note that the expression SimpleHandler(doit)
is simply a type conversion, it's not a function call. So there are no new values or anonymous functions created here in the background, this solution is the most efficient.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论