iface结构

iface结构

Content #

// $GOROOT/src/runtime/runtime2.go
type iface struct {
    tab  *itab
    data unsafe.Pointer
}

iface 用于表示非空的拥有方法的接口 interface 类型变量。

iface 除了要存储动态类型信息之外,还要存储接口本身的信息(接口的类型信息、方法列表信息等)以及动态类型所实现的方法的信息,因此 iface 的第一个字段指向一个itab类型结构。itab 结构的定义如下:

// $GOROOT/src/runtime/runtime2.go
type itab struct {
    inter *interfacetype
    _type *_type
    hash  uint32 // copy of _type.hash. Used for type switches.
    _     [4]byte
    fun   [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter.
}

itab 结构中的字段_type(参看 eface结构)则存储着这个接口类型变量的动态类型的信息。字段fun则是动态类型已实现的接口方法的调用地址数组。 itab 结构中的第一个字段inter指向的 interfacetype 结构,存储着这个接口类型自身的信息。interfacetype 结构由类型信息(typ)、包路径名(pkgpath)和接口方法集合切片(mhdr)组成。

// $GOROOT/src/runtime/type.go
type interfacetype struct {
    typ     _type
    pkgpath name
    mhdr    []imethod
}

我们来看一个用 iface 表示非空接口类型变量的例子:

type T struct {
    n int
    s string
}
func (T) M1() {}
func (T) M2() {}
type NonEmptyInterface interface {
    M1()
    M2()
}
func main() {
    var t = T{
        n: 18,
        s: "hello, interface",
    }
    var i NonEmptyInterface = t
}

和 eface 比起来,iface 的表示稍微复杂些。我也画了一幅表示上面 NonEmptyInterface 接口类型变量在 Go 运行时表示的示意图:

Viewpoint #

From #

29|接口:为什么nil接口不等于nil?