脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Golang - 深入了解Golang interface{}的底层原理实现

深入了解Golang interface{}的底层原理实现

2022-11-29 11:301个俗人 Golang

在 Go 语言没有泛型之前,接口可以作为一种替代实现,也就是万物皆为的 interface。那到底 interface 是怎么设计的底层结构呢?下面咱们透过底层分别看一下这两种类型的接口原理。感兴趣的小伙伴们可以参考借鉴,希望对大家能有

前言

Go 语言没有泛型之前,接口可以作为一种替代实现,也就是万物皆为的 interface。那到底 interface 是怎么设计的底层结构呢?下面咱们透过底层分别看一下这两种类型的接口原理。感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

interface数据结构

golang中的接口分为带方法的接口和空接口。 带方法的接口在底层用iface表示,空接口的底层则是eface表示。下面咱们透过底层分别看一下这两种数据结构。

iface

iface表示的是包含方法的interface;例如:

?
1
2
3
type Test interface{
    test()
}

底层源代码是:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//runtime/runtime2.go
 
//非空接口
type iface struct {
    tab  *itab
    data unsafe.Pointer //data是指向真实数据的指针
}
type itab struct {
    inter  *interfacetype //描述接口自己的类型
    _type  *_type         //接口内部存储的具体数据的真实类型
    link   *itab
    hash   uint32 // copy of _type.hash. Used for type switches.
    bad    bool   // type does not implement interface
    inhash bool   // has this itab been added to hash?
    unused [2]byte
    fun    [1]uintptr // fun是指向方法集的指针。它用于动态调度。
}
 
//runtime/type.go
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
    ptrToThis typeOff
}

和eface相同的是都有指向具体数据的指针data字段。 不同的是_type变成了tab。

  • hash 是对 _type.hash 的拷贝,当我们想将 interface 类型转换成具体类型时,可以使用该字段快速判断目标类型和具体类型 runtime._type 是否一致;
  • fun 是一个动态大小的数组,它是一个用于动态派发的虚函数表,存储了一组函数指针。虽然该变量被声明成大小固定的数组,但是在使用时会通过原始指针获取其中的数据;

深入了解Golang interface{}的底层原理实现

eface

eface顾名思义 empty interface,代表的是不包含方法的interface,例如:

?
1
type Test interface {}

因为空接口不包含任何方法,所以它的结构也很简单,底层源代码是:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//空接口
type eface struct {
    _type *_type         //接口内部存储的具体数据的真实类型
    data  unsafe.Pointer //data是指向真实数据的指针
}
 
//runtime/type.go
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
    ptrToThis typeOff
}

eface 结构体主要包含两个字段,共16字节。

  • _type:这个是运行时 runtime._type 指针类型,表示数据类型
  • data: 表示的数据指针

深入了解Golang interface{}的底层原理实现

总结

Go语言底层对非空interface和空interface实现上做了区分。空interface的底层结构是eface结构。它与iface的区别在于,它拥有的不再是 *itab类型数据,而是 _type 类型的数据。是因为,eface面向的是空的interface数据,既然是空的interface,那么只需要用 *_type 代表类型,data字段指向具体数据即可。这里的 *_type 是此interface代表的数据的类型。

到此这篇关于深入了解Golang interface{}的底层原理实现的文章就介绍到这了,更多相关Golang interface{}内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://juejin.cn/post/7157625818456260644

延伸 · 阅读

精彩推荐
  • GolangGolang 实现获取当前函数名称和文件行号等操作

    Golang 实现获取当前函数名称和文件行号等操作

    这篇文章主要介绍了Golang 实现获取当前函数名称和文件行号等操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    私念9392021-06-25
  • GolangGo秒爬博客园100页新闻

    Go秒爬博客园100页新闻

    利用go语言的协程并发优势爬取网页速度相当之快,博客园100页新闻标题只需一秒即可全部爬取,跟着小编一起去看看如何实现的,希望大家可以从中受益...

    大囚长5282020-05-19
  • GolangGo语言原子操作及互斥锁的区别

    Go语言原子操作及互斥锁的区别

    原子操作就是不可中断的操作,本文主要介绍了Go语言原子操作及互斥锁的区别,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙...

    小杰的快乐时光8372022-01-22
  • GolangGo语言基础变量的声明及初始化示例详解

    Go语言基础变量的声明及初始化示例详解

    这篇文章主要为大家介绍了Go语言基础变量的声明及初始化示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助祝大家多多进步,早日升职加薪...

    枫少文11202021-12-07
  • GolangGolang的循环语句和循环控制语句详解

    Golang的循环语句和循环控制语句详解

    循环语句为了简化程序中有规律的重复性操作,需要用到循环语句,和其他大多数编程语言一样,GO的循环语句有for循环,不同的是没有while循环,而循环控...

    曲鸟9012021-12-02
  • Golang详解Golang利用反射reflect动态调用方法

    详解Golang利用反射reflect动态调用方法

    这篇文章主要介绍了详解Golang利用反射reflect动态调用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋...

    Chen Jiehua5112020-05-21
  • GolangGo类型安全的HTTP请求示例详解

    Go类型安全的HTTP请求示例详解

    这篇文章主要为大家介绍了Go类型安全的HTTP请求示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪...

    万俊峰Kevin3372022-10-24
  • GolangGo1.18新特性使用Generics泛型进行流式处理

    Go1.18新特性使用Generics泛型进行流式处理

    这篇文章主要为大家介绍了Go1.18新特性使用Generics泛型进行流式处理详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职...

    摇摆的小虎牙11832022-10-20