A P*_*oor 0 types functional-programming interface function go
我读到,在 Go 中,函数可以实现接口(就像在这个例子或这个例子中)。
但是让一个函数实现一个接口有什么价值呢?
例如,为什么要花时间定义一个接口、一个新的函数类型和一个方法,像这样:
type Handler interface {
ServeHTTP(*Conn, *Request)
}
type HandlerFunc func(*Conn, *Request)
func (f HandlerFunc) ServeHTTP(c *Conn, req *Request) {
f(c, req)
}
Run Code Online (Sandbox Code Playgroud)
相反,您可以只创建一个像这样的函数:
func ServeHTTP(f func(*Conn, *Request), c *Conn, req *Request) {
f(c, req)
}
Run Code Online (Sandbox Code Playgroud)
提前致谢!
单个函数(在您的示例中,func ServeHTTP, 不满足任何接口。
因此,将方法附加到函数类型的原因是为了满足接口。
这其中有什么价值?让任何其他类型实现接口的价值相同。让我们看看http.Handler界面,因为你提出了它。
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
Run Code Online (Sandbox Code Playgroud)
例如,您可以使用结构实现此接口:
type myHanlder struct {
/* some fields */
}
func (s *myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
/* do things */
}
Run Code Online (Sandbox Code Playgroud)
你也可以用一些更简单的类型来满足它。说,一个字符串:
type myStringHandler string
func (h myStringHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
_, _ = fmt.Fprintf(w, "The string is: %s", h)
}
Run Code Online (Sandbox Code Playgroud)
但是如果您只想直接实现该功能,例如:
func myHandler(w http.ResponseWriter, r *http.Request) {
/* do things */
}
Run Code Online (Sandbox Code Playgroud)
这不满足接口。所以我们需要创建一个匹配函数签名的类型,并提供接口方法。这就是http.HandlerFunc它的作用:
type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
Run Code Online (Sandbox Code Playgroud)
如果问题是:为什么标准库的作者决定做ServerHTTP一个接口,而不是一个函数类型,而不用搜索旧的邮件列表档案来寻找线索,只有猜测是可能的,这在这里真的是题外话,但这里有一个小刺它:
http.Handler接口又满足其他接口的结构。如果http.Handler不是接口,。作为一个思想实验,想象一下如果io.Reader接口代替函数类型:
type Reader func(p []byte) (n int, err error)
Run Code Online (Sandbox Code Playgroud)
我认为很容易看出疯狂会随之而来。