美文网首页
Go interface源码解析-note

Go interface源码解析-note

作者: robertzhai | 来源:发表于2023-01-30 10:28 被阅读0次

    interface底层使用2个struct表示:eface和iface , 位置 src/runtime/runtime2.go

    image.png
    image.png
    // 有方法的接口 iface 非空接口
    type iface struct {
        tab  *itab
        data unsafe.Pointer //指向原始数据指针
    }
    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.
    }
    // runtime/type.go
    // 非空接口类型,接口定义,包路径等。
    type interfacetype struct {
       typ     _type
       pkgpath name
       mhdr    []imethod      // 接口方法声明列表,按字典序排序
    }
    
    
    
    // 接口的方法声明,一种函数声明的抽象
    // 比如:func Print() error
    type imethod struct {
       name nameOff          // 方法名
       ityp typeOff                // 描述方法参数返回值等细节
    }
    
    type nameOff int32
    type typeOff int32
    method 存的是func 的声明抽象,而 itab 中的 fun 字段才是存储 func 的真实切片。
    
    
    // 没有方法的接口 eface 空接口定义
    type eface struct {
        _type *_type //类型信息
        data  unsafe.Pointer  //数据信息,指向数据指针
    }
    type _type struct {
        size       uintptr
        ptrdata    uintptr // size of memory prefix holding all pointers
        hash       uint32
        tflag      tflag
        align      uint8
        fieldAlign uint8
        kind       uint8
        // function for comparing objects of this type
        // (ptr to object A, ptr to object B) -> ==?
        equal func(unsafe.Pointer, unsafe.Pointer) bool
        // 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
        ptrToThis typeOff
    }
    

    没有方法的interface赋值后内部结构

    import (
        "fmt"
        "strconv"
    )
    
    type Binary uint64
    
    func main() {
        b := Binary(200)
        any := (interface{})(b)
        fmt.Println(any)
    }
    

    输出200,赋值后的结构图是这样的


    image.png

    iface 非空接口

    非空接口(iface)本身除了可以容纳满足其接口的对象之外,还需要保存其接口的方法,因此除了data字段,iface通过tab字段描述非空接口的细节,包括接口方法定义,接口方法实现地址,接口所指类型等。iface是非空接口的实现,而不是类型定义,iface的真正类型为interfacetype,其第一个字段仍然为描述其自身类型的_type字段。


    image.png

    含有方法的interface赋值后的内部结构

    package main
    
    import (
        "fmt"
        "strconv"
    )
    
    type Binary uint64
    func (i Binary) String() string {
        return strconv.FormatUint(i.Get(), 10)
    }
    
    func (i Binary) Get() uint64 {
        return uint64(i)
    }
    
    func main() {
        b := Binary(200)
        any := fmt.Stringer(b)
        fmt.Println(any)
    }
    

    赋值后接口Stringer的内部结构为


    image.png

    ref

    相关文章

      网友评论

          本文标题:Go interface源码解析-note

          本文链接:https://www.haomeiwen.com/subject/dwdphdtx.html