为什么要在Go中的函数上实现接口?

我读到,在 Go 中,函数可以实现接口(就像在这个例子或这个例子中)。

但是让一个函数实现一个接口有什么价值呢?

例如,为什么要花时间定义一个接口、一个新的函数类型和一个方法,像这样:

type Handler interface {
    ServeHTTP(*Conn, *Request)
}

type HandlerFunc func(*Conn, *Request)

func (f HandlerFunc) ServeHTTP(c *Conn, req *Request) {
    f(c, req)
}

相反,您可以只创建一个像这样的函数:

func ServeHTTP(f func(*Conn, *Request), c *Conn, req *Request) {
    f(c, req)
}

提前致谢!

回答

单个函数(在您的示例中,func ServeHTTP, 不满足任何接口。

因此,将方法附加到函数类型的原因是为了满足接口

这其中有什么价值?让任何其他类型实现接口的价值相同。让我们看看http.Handler界面,因为你提出了它。

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

例如,您可以使用结构实现此接口:

type myHanlder struct {
   /* some fields */
}

func (s *myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    /* do things */
}

你也可以用一些更简单的类型来满足它。说,一个字符串:

type myStringHandler string

func (h myStringHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    _, _ = fmt.Fprintf(w, "The string is: %s", h)
}

但是如果您只想直接实现该功能,例如:

func myHandler(w http.ResponseWriter, r *http.Request) {
    /* do things */
}

这不满足接口。所以我们需要创建一个匹配函数签名的类型,并提供接口方法。这就是http.HandlerFunc它的作用:

type HandlerFunc func(ResponseWriter, *Request)

func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    f(w, r)
}

如果问题是:为什么标准库的作者决定做ServerHTTP一个接口,而不是一个函数类型,而不用搜索旧的邮件列表档案来寻找线索,只有猜测是可能的,这在这里真的是题外话,但这里有一个小刺它:

  • 接口更易于使用,因为它们可以轻松扩展/嵌入。也就是说,我可以实现一个既满足http.Handler接口又满足其他接口的结构。如果http.Handler不是接口,。
  • 这是惯用的。使用“鸭子打字”界面正好符合 Go 的做事方式。也许这有点同义反复,因为它适合 Go 的原因是因为它是这样做的。
  • 如果您有一个复杂的处理程序,它可能会跟踪自己的状态,那么使用结构是自然的解决方案,并且将其公开为接口比闭包更自然(如果将其实现为函数类型,则需要这样做)。

作为一个思想实验,想象一下如果io.Reader接口代替函数类型:

type Reader func(p []byte) (n int, err error)

我认为很容易看出疯狂会随之而来。


以上是为什么要在Go中的函数上实现接口?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>