AnthonyZero's Bolg

Go使用技巧 接口型函数

介绍

函数和其他类型一样都属于“一等公民”,其他类型能够实现接口,函数也可以。这种在调用的时候就会非常简便,这种函数,称为接口型函数,这种方式使用于只有一个函数的接口。

这样,既能够将普通的函数类型(需类型转换)作为参数,也可以将结构体作为参数,使用更为灵活,可读性也更好,这就是接口型函数的价值。

代码

在使用的时候我们有三种方式:struct对象/匿名函数/普通函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
type Service interface {
Call(key string)
}

type ServiceFunc func(key string)

func (s ServiceFunc) Call(key string) {
s(key)
}

type EchoService struct{}

func (echo EchoService) Call(key string) {
fmt.Println("echo service call, key : ", key)
}

func PrintKey(key string) {
fmt.Println("print key:", key)
}

func Foo(s Service, key string) {
s.Call(key)
}

func main() {
Foo(new(EchoService), "echo") //struct 作为参数

Foo(ServiceFunc(func(key string) {
fmt.Println("service func, call key,", key)
}), "serviceFunc") //匿名函数就地实现 上面的接口型函数

Foo(ServiceFunc(PrintKey), "printkey") //普通函数为参数 上面的接口型函数类型
}

HTTP包中的例子

HTTP 包中包含有 Handler 接口定义,代码如下:

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

Handler 用于定义每个 HTTP 的请求和响应的处理过程。

同时,也可以使用处理函数(接口型函数)实现接口,定义如下:

1
2
3
4
5
6
7
type HandlerFunc func(ResponseWriter, *Request)

// ServeHTTP calls f(w, r). 调用自己,这样就实现了接口 Handler
// 所以 HandlerFunc 是一个实现了Handler接口的函数类型,简称为接口型函数
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}

要使用闭包实现默认的 HTTP 请求处理,可以使用 http.HandleFunc() 函数,函数定义如下:

1
2
3
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}

而 DefaultServeMux 是 ServeMux 结构,拥有 HandleFunc() 方法,定义如下:

1
2
3
4
5
6
7
//HandleFunc registers the handler function for the given pattern.
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
if handler == nil {
panic("http: nil handler")
}
mux.Handle(pattern, HandlerFunc(handler))
}

上面代码将外部传入的函数 handler() 转为 HandlerFunc 类型,HandlerFunc函数类型实现了 Handler 的 ServeHTTP 方法,底层可以同时使用各种类型来实现 Handler 接口进行处理。