golang interface学习笔记

Posted by Jason on Sunday, January 20, 2019

TOC

本文通过阅读go interface源码剖析深入理解 Go Interface两篇文章,通过一些个人思考补充完成,在此感谢作者的分享,如有侵权请告知。

概念

开始前先copy一个概念(出自参考1):

In object-oriented programming, a protocol or interface is a common means for unrelated objects to communicate with each other. These are definitions of methods and values which the objects agree upon in order to co-operate. — wikipedia

这是 wikipedia 关于 protocal 的定义,将 interface 类比如 protocal 是一种非常助于理解的方式。protocol,中文一般叫做协议,比如网络传输中的 TCP 协议。protocol 可以认为是一种双方为了交流而做出的约定,interface 可以类比如此。

why interface

(参考2)中提到在gopher大会上Francesc大神提出interface提出的几个理由:

  • writing generic algorithm (泛型编程)
  • hiding implementation detail (隐藏具体实现)
  • providing interception points

这三个内容具体介绍可以看(参考3)或者(参考2)中的详细介绍。

其中文章提到在我们设计函数的时候,有一个比较好的准则。

Be conservative in what you send, be liberal in what you accept. — Robustness Principle

具体对应到 Golang 就是:

Return concrete types, receive interfaces as parameter. — Robustness Principle applied to Go 返回值要非常明确,入参可以更宽泛一些。

特此记录一下,当然这不是一个必须遵守的准则,因为golang源码中就没有完全依照它设计函数,可以作为一个参考。

interface结构

在golang底层对interface实现的数据结构,有两个,一个是iface、eface,具体定义在源码go/src/runtime/runtime2.go。其中eface是存储不带函数的interface,相反iface存储带有函数的。

type iface struct {
    tab  *itab  // 如果未初始化的接口,这个指针为零
    data unsafe.Pointer //保存数据的指针
}

type itab struct {
    inter *interfacetype //指向具体接口定义数据地址
    _type *_type   // 指向结构体类型的指针
    hash  uint32   // 结构体类型中的hash值,进行断言时会用到。为什么要拿出来?
    _     [4]byte  //个人理解为了字节对齐
    fun   [1]uintptr // 类似c++中的虚函数表,存储函数的地址,参考2中验证了对于多个函数情况下,会按方法名字典排序
}

type interfacetype struct {
    typ     _type //接口类型
    pkgpath name  //包路径
    mhdr    []imethod //指向相应名字的offset的列表和interface 所暴露的方法的类型
}

type imethod struct {
    name nameOff
    ityp typeOff
}
--------------------------------------

type _type struct {
    size       uintptr
    ptrdata    uintptr // size of memory prefix holding all pointers
    hash       uint32
    tflag      tflag
    align      uint8
    fieldalign uint8
    kind       uint8
    alg        *typeAlg
    // gcdata stores the GC type data for the garbage collector.
    // If the KindGCProg bit is set in kind, gcdata is a GC program.
    // Otherwise it is a ptrmask bitmap. See mbitmap.go for details.
    gcdata    *byte
    str       nameOff //结构体名字相对于可执行文件的元信息的偏移量,resolveNameOff(t, t.str) 获取类型名字
    ptrToThis typeOff //结构体类型相对于可执行文件的元信息的偏移量,可以通过resolveTypeOff(t, t.ptrToThis) 就可以返回 t 的一份拷贝
}

------------------------------------------------------------------------------

type eface struct {
    _type *_type  //指向结构体类型地址
    data  unsafe.Pointer //保存数据的指针
}

其中

参考

  1. go interface源码剖析
  2. 深入理解 Go Interface
  3. understanding golang interface(Gopher China) — youtube
  4. github Interfaces

「真诚赞赏,手留余香」

Jason Blog

真诚赞赏,手留余香

使用微信扫描二维码完成支付


comments powered by Disqus