【译】Go语言中方法实现接口

Published: by Creative Commons Licence

原文地址: https://karthikkaranth.me/blog/functions-implementing-interfaces-in-go

Go 语言中,可以用方法实现接口。这很灵巧,你不用创建一个结构体,就可以轻松的创建一个接口的实现,这个实现可以称为"一个方法-接口"(one-function interfaces)。

net/http 包下面的 HandleFunc 方法就是一个例子,如果你看过 Handler 的源代码,你可以看到,这是一个只包含单函数的接口:

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

现在,向下滑动一点,你将看到HandlerFunc的定义:

type HandlerFunc func(ResponseWriter, *Request)

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

这很高效,对于开发者来说,可以在接收Handler (interface)为参数的任意函数中传递HandlerFunc 函数作为入参。

所以,可以这样写:

func PongHandler(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("pong"))
}

func main() {
    handler := http.HandlerFunc(PongHandler)
    http.Handle("/ping", handler)
    http.ListenAndServe(":8080", nil)
}

(但是尽量不要这么做,在这个例子中用http.HandleFunc1替代,这样会更清晰)

更有趣的是,在Go语言中任意类型都可以实现接口。下面就是一个无符号整型的计数器例子,它实现了Handler接口:

type Counter uint64

func (i *Counter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	*i++
	response := fmt.Sprintf("%v", *i)
	w.Write([]byte(response))
}

func main() {
	var c Counter
	http.Handle("/count", &c)
	http.ListenAndServe(":8080", nil)
}
  1. 作者在这个例子中两次提到http.Handle.Func, 容易造成混淆,这里解释一下。 第一次handler := http.HandlerFunc(PongHandler)中是指类型强制转化,第二次是http包的HandleFunc函数。