文章目录

  • GoLang之iface 和 eface 的区别是什么(3)
  • 参考资料

GoLang之iface 和 eface 的区别是什么(3)

ifaceeface 都是 Go 中描述接口的底层结构体,区别在于 iface 描述的接口包含方法,而 eface 则是不包含任何方法的空接口:interface{}

从源码层面看一下:

type iface struct {tab  *itabdata unsafe.Pointer
}type itab struct {inter  *interfacetype_type  *_typelink   *itabhash   uint32 // copy of _type.hash. Used for type switches.bad    bool   // type does not implement interfaceinhash bool   // has this itab been added to hash?unused [2]bytefun    [1]uintptr // variable sized
}

iface 内部维护两个指针,tab 指向一个 itab 实体, 它表示接口的类型以及赋给这个接口的实体类型。data 则指向接口具体的值,一般而言是一个指向堆内存的指针。

再来仔细看一下 itab 结构体:_type 字段描述了实体的类型,包括内存对齐方式,大小等;inter 字段则描述了接口的类型。fun 字段放置和接口方法对应的具体数据类型的方法地址,实现接口调用方法的动态分派,一般在每次给接口赋值发生转换时会更新此表,或者直接拿缓存的 itab。

这里只会列出实体类型和接口相关的方法,实体类型的其他方法并不会出现在这里。如果你学过 C++ 的话,这里可以类比虚函数的概念。

另外,你可能会觉得奇怪,为什么 fun 数组的大小为 1,要是接口定义了多个方法可怎么办?实际上,这里存储的是第一个方法的函数指针,如果有更多的方法,在它之后的内存空间里继续存储。从汇编角度来看,通过增加地址就能获取到这些函数指针,没什么影响。顺便提一句,这些方法是按照函数名称的字典序进行排列的。

再看一下 interfacetype 类型,它描述的是接口的类型:

type interfacetype struct {typ     _typepkgpath namemhdr    []imethod
}

可以看到,它包装了 _type 类型,_type 实际上是描述 Go 语言中各种数据类型的结构体。我们注意到,这里还包含一个 mhdr 字段,表示接口所定义的函数列表, pkgpath 记录定义了接口的包名。

这里通过一张图来看下 iface 结构体的全貌:

接着来看一下 eface 的源码:

type eface struct {_type *_typedata  unsafe.Pointer
}

相比 ifaceeface 就比较简单了。只维护了一个 _type 字段,表示空接口所承载的具体的实体类型。data 描述了具体的值。

我们来看个例子:

package mainimport "fmt"func main() {x := 200var any interface{} = xfmt.Println(any)g := Gopher{"Go"}var c coder = gfmt.Println(c)
}type coder interface {code()debug()
}type Gopher struct {language string
}func (p Gopher) code() {fmt.Printf("I am coding %s language\n", p.language)
}func (p Gopher) debug() {fmt.Printf("I am debuging %s language\n", p.language)
}

执行命令,打印出汇编语言:

go tool compile -S ./src/main.go

可以看到,main 函数里调用了两个函数:

func convT2E64(t *_type, elem unsafe.Pointer) (e eface)
func convT2I(tab *itab, elem unsafe.Pointer) (i iface)

上面两个函数的参数和 ifaceeface 结构体的字段是可以联系起来的:两个函数都是将参数组装一下,形成最终的接口。

作为补充,我们最后再来看下 _type 结构体:

type _type struct {// 类型大小size       uintptrptrdata    uintptr// 类型的 hash 值hash       uint32// 类型的 flag,和反射相关tflag      tflag// 内存对齐相关align      uint8fieldalign uint8// 类型的编号,有bool, slice, struct 等等等等kind       uint8alg        *typeAlg// gc 相关gcdata    *bytestr       nameOffptrToThis typeOff
}

Go 语言各种数据类型都是在 _type 字段的基础上,增加一些额外的字段来进行管理的:

type arraytype struct {typ   _typeelem  *_typeslice *_typelen   uintptr
}type chantype struct {typ  _typeelem *_typedir  uintptr
}type slicetype struct {typ  _typeelem *_type
}type structtype struct {typ     _typepkgPath namefields  []structfield
}

这些数据类型的结构体定义,是反射实现的基础。

参考资料

【有汇编分析,不错】http://legendtkl.com/2017/07/01/golang-interface-implement/

【interface 源码解读 很不错 包含反射】http://wudaijun.com/2018/01/go-interface-implement/

GoLang之iface 和 eface 的区别是什么(3)相关推荐

  1. GoLang之iface 和 eface 的区别是什么?

    GoLang之iface 和 eface 的区别是什么? iface 和 eface 都是 Go 中描述接口的底层结构体,区别在于 iface 描述的接口包含方法,而 eface 则是不包含任何方法的 ...

  2. Golang之接口底层分析

    目录 GoLang之iface 和 eface 的区别是什么? GoLang之接口的动态类型和动态值 [引申1]接口类型和 `nil` 作比较 [引申2] [引申3]如何打印出接口的动态类型和值? G ...

  3. golang 接口类型 interface 简介

    目录 1. Go 语言与鸭子类型的关系 2. 值接收者和指针接收者的区别 方法 值接收者和指针接收者 两者分别在何时使用 3. iface 和 eface 的区别是什么 4. 接口的动态类型和动态值 ...

  4. golang 接口类型 interface 简介使用

    1. Go 语言与鸭子类型的关系 先直接来看维基百科里的定义: If it looks like a duck, swims like a duck, and quacks like a duck, ...

  5. 两万字深入解密 Go 语言接口的那些事儿 | 技术头条

    Go 语言的接口的原理是什么?是如何使用?它和C++接口有什么异同呢?本文作者用两万多字深入一一为你讲述Go语言interface的那些事儿. 作者 | 饶全成 责编 | 伍杏玲 这篇文章的架构比较简 ...

  6. 深度解密Go语言之关于 interface 的 10 个问题

    12这次文章依然很长,基本上涵盖了 interface 的方方面面,有例子,有源码分析,有汇编分析,前前后后写了 20 多天.洋洋洒洒,长篇大论,依然有些东西没有涉及到,比如文章里没有写到反射,当然, ...

  7. go 调用c 编译器找不到方法_深度解密Go语言之关于 interface 的10个问题

    这次文章依然很长,基本上涵盖了 interface 的方方面面,有例子,有源码分析,有汇编分析,前前后后写了 20 多天.洋洋洒洒,长篇大论,依然有些东西没有涉及到,比如文章里没有写到反射,当然,后面 ...

  8. golang个人整理知识点

    环境变量: GOPATH: window下默认值路径为%USERPROFILE%/go,可以删掉新建,然后所有的项目代码放在src子目录下 GOPATH路径下有三个目录src pkg bin 具体的子 ...

  9. Golang知识总结

    1 GOLong对比各语言异同. C/C++:直接编译成机器码,不需要执行环境,所以一次编码只能适用于一种平台 ​ 需要自己处理GC问题 JAVA:编译为中间码(字节码) ​ 需要特定的执行环境(JV ...

  10. Golang精编100题-搞定golang面试

    Golang精编100题 能力模型 级别 模型 初级 primary 熟悉基本语法,能够看懂代码的意图: 在他人指导下能够完成用户故事的开发,编写的代码符合CleanCode规范: 中级 interm ...

最新文章

  1. JQuery.Ajax()的data参数传递方式
  2. 小菜学习Lucene.Net(更新3.0.3版本使用)
  3. 强化学习总结(1-2)——model-base(policy evaluation;policy control)
  4. ssl提高组周四备考赛【2018.11.1】
  5. 有关fwrite语句的用法
  6. 纪念诺贝尔生理医学奖获得者 Sydney Brenner (1927-2019)
  7. 最新js实现复制粘贴功能实例
  8. 剑指offer——面试题39-2:平衡二叉树
  9. 《剑指offer》-中序遍历下一个节点
  10. 小米3g刷高格固件_不走弯路:小米路由器3G 刷Padavan固件简单教程
  11. pytorch基础(四):使用optim优化函数
  12. 软考之---软件设计师考试经验与笔记分享
  13. Win10安装Kafka步骤
  14. 哪个牌子的蓝牙耳机音质好?音质比较好的蓝牙耳机排名
  15. macOS hashcat 安装
  16. IP地址查询在线查询
  17. cleanup(cleanup什么意思中文)
  18. 一个2层隐层神经网络解决抑或问题
  19. Revit中复合墙图层的规则和CAD识别翻模墙
  20. 用html语言编写彩虹雨流动代码,canvas实现爱心和彩虹雨效果

热门文章

  1. Postgresql 学习记录,模式,分区表,触发器,事务,窗口函数,视图,建表,约束等
  2. 【转载】Unity 项目管理与优化
  3. java自己写母版_Java 创建并用应用幻灯片母版
  4. 浅谈功能测试-->自动化测试
  5. 嵌入式系统设计师考试完美笔记
  6. MSET key value [key value ...]
  7. VS2008下 天龙客户端编译
  8. 修改计算机ip地址cmd,有谁能告诉我怎么用cmd指令修改自己电脑的IP地址
  9. windows 键盘快捷键
  10. 解决微信端苹果手机无法跳转页面