• go语言接口型函数使用


    转载自:https://geektutu.com/post/7days-golang-q1.html

    在 动手写分布式缓存 - GeeCache第二天 单机并发缓存 这篇文章中,有一个接口型函数的实现:
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // A Getter loads data for a key.
    type Getter interface {
        Get(key string) ([]byte, error)
    }
    
    // A GetterFunc implements Getter with a function.
    type GetterFunc func(key string) ([]byte, error)
    
    // Get implements Getter interface function
    func (f GetterFunc) Get(key string) ([]byte, error) {
        return f(key)
    }
    这里呢,定义了一个接口 Getter,只包含一个方法 Get(key string) ([]byte, error),紧接着定义了一个函数类型 GetterFunc,GetterFunc 参数和返回值与 Getter 中 Get 方法是一致的。而且 GetterFunc 还定义了 Get 方式,并在 Get 方法中调用自己,这样就实现了接口 Getter。所以 GetterFunc 是一个实现了接口的函数类型,简称为接口型函数。
    
    这个接口型函数的实现就引起了好几个童鞋的关注。接口型函数只能应用于接口内部只定义了一个方法的情况,例如接口 Getter 内部有且只有一个方法 Get。既然只有一个方法,为什么还要多此一举,封装为一个接口呢?定义参数的时候,直接用 GetterFunc 这个函数类型不就好了,让用户直接传入一个函数作为参数,不更简单吗?
    
    所以呢,接口型函数的价值什么?
    
    价值
    我们想象这么一个使用场景,GetFromSource 的作用是从某数据源获取结果,接口类型 Getter 是其中一个参数,代表某数据源:
    
    1
    2
    3
    4
    5
    6
    7
    func GetFromSource(getter Getter, key string) []byte {
        buf, err := getter.Get(key)
        if err == nil {
            return buf
        }
        return nil
    }
    我们可以有多种方式调用该函数:
    
    方式一:GetterFunc 类型的函数作为参数
    1
    2
    3
    GetFromSource(GetterFunc(func(key string) ([]byte, error) {
        return []byte(key), nil
    }), "hello")
    支持匿名函数,也支持普通的函数:
    
    1
    2
    3
    4
    5
    6
    7
    func test(key string) ([]byte, error) {
        return []byte(key), nil
    }
    
    func main() {
        GetFromSource(GetterFunc(test), "hello")
    }
    将 test 强制类型转换为 GetterFunc,GetterFunc 实现了接口 Getter,是一个合法参数。这种方式适用于逻辑较为简单的场景。
    
    方式二:实现了 Getter 接口的结构体作为参数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    type DB struct{ url string}
    
    func (db *DB) Query(sql string, args ...string) string {
        // ...
        return "hello"
    }
    
    func (db *DB) Get(key string) ([]byte, error) {
        // ...
        v := db.Query("SELECT NAME FROM TABLE WHEN NAME= ?", key)
        return []byte(v), nil
    }
    
    func main() {
        GetFromSource(new(DB), "hello")
    }
    DB 实现了接口 Getter,也是一个合法参数。这种方式适用于逻辑较为复杂的场景,如果对数据库的操作需要很多信息,地址、用户名、密码,还有很多中间状态需要保持,比如超时、重连、加锁等等。这种情况下,更适合封装为一个结构体作为参数。
    
    这样,既能够将普通的函数类型(需类型转换)作为参数,也可以将结构体作为参数,使用更为灵活,可读性也更好,这就是接口型函数的价值。
    
    使用场景
    这个特性在 groupcache 等大量的 Go 语言开源项目中被广泛使用,标准库中用得也不少,net/http 的 Handler 和 HandlerFunc 就是一个典型。
    
    我们先看一下 Handler 的定义:
    
    1
    2
    3
    4
    5
    6
    7
    8
    type Handler interface {
        ServeHTTP(ResponseWriter, *Request)
    }
    type HandlerFunc func(ResponseWriter, *Request)
    
    func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
        f(w, r)
    }
  • 相关阅读:
    _CrtSetBreakAlloc(…)来检测内存泄漏+VC使用CRT调试功能检测内存泄漏(转)
    VC 2005 解决方案的目录结构设置和管理
    ArcGIS Engine基础开发教程(转)
    vc++实现avi文件的操作 用于视频解析及录制(转)
    微软免费杀毒软件下周二公测 年底推简体中文版 狼人:
    大量用户升级iPhone3.0系统导致苹果服务器故障 狼人:
    苹果发布45个iPhone和iTouch漏洞补丁 狼人:
    “汉网热血三国”“南方电视台”等网站被挂马 狼人:
    WAPI有望晋身国际标准 最大阻力美国首度支持 狼人:
    前Google员工推云安全服务检测网站挂马 狼人:
  • 原文地址:https://www.cnblogs.com/kekemuyu/p/14188321.html
Copyright © 2020-2023  润新知