深入 go interface 底层原理

打个广告:欢迎关注我的微信公众号,在这里您将获取更全面、更新颖的文章!

原文链接:深入 go interface 底层原理 欢迎点赞关注

什么是 interface

在 Go 语言中,interface(接口)是一种抽象的类型定义。它主要用于定义一组方法的签名,但不包含方法的实现细节。接口提供了一种规范,任何类型只要实现了接口中定义的所有方法,就被认为是实现了该接口。这使得不同的类型可以以一种统一的方式被处理,增强了代码的灵活性、可扩展性和可维护性。

例如,如果定义一个 Shape 接口,包含一个 Area 方法:

type Shape interface {
    Area() float64
}

// 圆形结构体
type Circle struct {
    Radius float64
}

// 圆形实现面积计算方法
func (c Circle) Area() float64 {
    return 3.14 * c.Radius * c.Radius
}

// 矩形结构体
type Rectangle struct {
    Length, Width float64
}

// 矩形实现面积计算方法
func (r Rectangle) Area() float64 {
    return r.Length * r.Width
}

// 打印形状面积的函数
func printArea(s Shape) {
    fmt.Printf("面积: %.2f\n", s.Area())
}

func main() {
    circle := Circle{Radius: 5}
    rectangle := Rectangle{Length: 4, Width: 6}

    printArea(circle)
    printArea(rectangle)
}

那么无论是 Circle 结构体还是 Rectangle 结构体,只要它们都实现了 Area 方法,就都可以被当作 Shape 类型来使用。

接口在 Go 语言中广泛应用于解耦代码、实现多态性、定义通用的行为规范等场景。它让代码更加模块化和易于管理,有助于提高代码的质量和可复用性。

底层数据结构

在 Go 语言中,有两种“interface”,一种是空接口(`interface{}`),它可以存储任意类型的值;另一种是非空接口,这种接口明确地定义了一组方法签名,只有实现了这些方法的类型才能被认为是实现了该非空接口。 下面讨论一下这两种接口的底层实现。

空接口与非空接口

在 Go 语言中,空接口的底层数据结构是 runtime.eface :

type eface struct {
    _type *_type
    data  unsafe.Pointer
}

_type 字段指向一个 _type 结构体,该结构体包含了所存储值的详细类型信息,data 字段则是一个 unsafe.Pointer ,它直接指向实际存储的数据的内存地址。

非空接口的底层数据结构是 runtime.iface:

type iface struct {
    tab  *itab
    data unsafe.Pointer
}

同样,data 字段也是一个指向实际数据的指针。然而,这里的重点是 tab 字段,它指向一个 itab 结构体。

itab 结构体

itab 结构体包含接口的类型信息和指向数据的类型信息:

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.
}

type interfacetype struct {
    typ     _type // 接口的类型
    pkgpath name  // 接口所在路径
    mhdr    []imethod // 接口所定义的方法列表
}
  1. inter 字段描述了接口自身的类型信息,包括接口所定义的方法等。

  2. _type 字段存储了实际值的类型信息。

  3. hash 字段是对 _type 结构体中哈希值的拷贝,它在进行类型比较和转换等操作时能够提供快速的判断依据。

  4. fun 字段则是一个动态大小的函数指针数组,当fun[0]=0时,表示_type并没有实现该接口(这里指的是itab下的_type),当实现了接口时,fun存放了第一个接口方法的地址,其他方法依次往后存放。在这里fun存储的其实是接口方法对应的实际类型的方法,每次调用发方法时实行动态分派。

_type 结构体

_type是runtime对Go任意类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值