使用接受 io.Writer 作为 HandleFunc 的函数。

huangapple go评论78阅读模式
英文:

Use function that accepts io.Writer as HandleFunc

问题

我想创建一个函数,可以作为httpHandleFunc,同时也可以使用另一个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.Writerhttp.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) 只是一种类型转换,它不是函数调用。因此,在后台没有创建新值或匿名函数,这种解决方案是最高效的。

英文:

Spec: Function types:

> 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.

huangapple
  • 本文由 发表于 2017年2月8日 15:57:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/42107579.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定