• 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 接口进行处理。

  • 相关阅读:
    移动端a标签点击图片有阴影处理
    sublime vue 语法高亮插件安装
    mongodb 命令
    MongoDB给数据库创建用户
    windows32位系统 安装MongoDB
    ES6之主要知识点(十)Proxy
    ES6之主要知识点(九)Set和Map
    ES6之主要知识点(八)Symbol
    ES6之主要知识点(七)对象
    Ueditor 1.4.3 插入表格后无边框无颜色,不能正常显示
  • 原文地址:https://www.cnblogs.com/zuoyang/p/15905634.html
Copyright © 2020-2023  润新知