Go从入门到精通——函数类型实现接口(把函数作为接口来调用)

函数类型实现接口(把函数作为接口来调用)

  函数和其他类型一样都属于 "一等公民",其他类型能够实现接口,函数也可以。

  我们对比下结构体和函数实现接口的过程。

  先实现一个接口:

//调用器接口
type Invoker interface {
    //需要实现一个 Call() 方法
    Call(interface())
}

  这个接口需要实现 Call() 方法,调用时会传入一个 interface{} 类型的变量,这种类型的变量表示任意类型的值。

1、结构体实现接口

  结构体实现 Invoker 接口的代码如下:

//结构体类型
type Struct struct{
}

//实现 Invoker 的 Call
func (s *Struct) Call(p interface{}){
    fmt.Println("from struct", p)
}

  代码说明如下:

  • 第 2 行,定义结构体,该例子中的结构体无须任何成员,主要展示实现 Invoker 的方法。
  • 第 6 行,Call() 为结构体的方法,该方法的功能是打印 from struct 和传入的 interface{} 类型的值。

  将 struct 类型实例化下,并传入接口中进行调用,代码如下:

//声明接口的变量
var invoker Invoker

//实例化结构体
s := new(Struct) //也可以写成 s := &Struct

//将实例化的结构体赋值到接口
invoker = s

//使用接口调用实例化结构体的方法 Struct.Call
invoker.Call("hello")

2、函数体实现接口

  函数的声明不能直接实现接口,需要将函数定义为类型后,使用类型实现结构体。当类型方法被调用时,还需要调用函数本体。

// 函数定义为类型
type FuncCall func(interface{})

// 实现 Invoker 的 Call
func (f FuncCaller) Call(p interface{}){
    //调用 f() 函数本体
    f(p)
}

  代码说明如下:

  • 第 2 行,将 func(interface{})定义为 FuncCaller 类型。
  • 第 5 行,FuncCaller 的 Call() 方法将实现 Invoker 的 Call() 方法。
  • 第 8 行,FuncCaller 的 Call() 方法调用与 func(interface{}) 无关,还需要手动调用函数本体。

  上面代码只是定义了函数类型,需要函数本身进行逻辑处理。FuncCaller 无须被实例化,只需要将函数转换为 FuncCaller 类型即可,函数来源可以是命名函数、匿名函数或闭包,代码如下:

//声明接口变量
var invoker Invoker

//将匿名函数转为 FuncCaller 类型,再赋值给接口
invoker = FuncCaller(func(v interface{})){
    fmt.Println("from function", v)
}

//使用接口调用 FuncCaller.Call,内部会调用函数本体
invoker.Call("hello")

  代码说明如下:

  • 第 2 行,声明接口变量。
  • 第 5 行,将 func(v interface{}) {} 匿名函数转换为 FuncCaller 类型(函数签名才能转换),此时 FuncCaller 类型实现了 Invoker 的 Call() 方法,赋值给 invoker 接口是成功的。
  • 第 10 行,使用接口方法调用。

  代码输出如下:

from function hello

3、HTTP 包中的例子

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

package main

type Handler interface{
    ServerHTTP(ResponseWrite, *Request)
}

  Handler 用于定义每个 HTTP 请求和响应的处理过程。
  同时,也可以使用处理函数实现接口,定义如下:

type HandlerFunc func(ResponseWrite, *Request)

func (f HandlerFunc) ServerHTTP(w ResponseWrite, r *ResponseWrite){
    f(w,r)
}

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

func HandlerFunc(pattern string, handler func(ResponseWrite, *Request)){
    DefaultServeMux.HandlerFunc(pattern,handler)
}

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

func (mxu *ServeMux) HandlerFunc(pattern string,hanlder func 
(ResponseWrite, *Request){
    mux.Handle(pattern,HandlerFunc(handler))
}

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

posted @ 2022-05-16 23:58  左扬  阅读(254)  评论(0编辑  收藏  举报
levels of contents