golang 接口的底层实现
Golang将interface作为一种类型,并且不依赖继承,而是以一种类似于duck-typing的实现。所谓duck-typing,是一种动态类型风格:当一个obj走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么它就可以被称为鸭子。
既然Go并没有像C++那样要求主动告诉编译器需要继承哪个父类,那么是如何实现动态类型的呢?(基于Go1.6,1.7及之后版本由于nameOff不方便gdb打印)
首先,interface由两部分组成{tab, data},其中tab保存了接口的元数据,这个很重要。
type iface struct {
tab *itab
data unsafe.Pointer
}
itab中比较重要的有interfacetype及fun[],其中interfacetype保存了该接口需要实现哪些方法,fun[]则保存动态类型是如何实现这些方法的
type itab struct {
inter *interfacetype
_type *_type
link *itab
bad int32
unused int32
fun [1]uintptr // variable sized
}
type interfacetype struct {
typ _type
mhdr []imethod
}
type imethod struct {
name *string
pkgpath *string
_type *_type
}
附:一篇经典论文中的图解
e.g. 唐老鸭的go版本
package main
import (
“fmt”
)
type Duck interface {
GaGaSpeaking()()
OfficialWalking()()
}
type Actor interface {
MakeFun()()
}
type DonaldDuck struct {
height uint
name string
}
func (dd *DonaldDuck) GaGaSpeaking()() {
fmt.Println(“DonaldDuck gaga”)
}
func (dd *DonaldDuck) OfficialWalking()() {
fmt.Println(“DonaldDuck walk”)
}
func (dd *DonaldDuck) MakeFun()() {
fmt.Println(“DonaldDuck make fun”)
}
func main() {
dd := &DonaldDuck{10, "tang lao ya" }
var duck Duck = dd
var actor Actor = dd
duck.GaGaSpeaking()
actor.MakeFun()
dd.OfficialWalking()
}
我们用gdb调试一下
首先,看下结构类型与两个接口的内存关系
(gdb) p dd
$1 = (struct main.DonaldDuck *) 0xc82000e180
(gdb) p duck
$2 = {tab = 0x7ffff7f721c0, data = 0xc82000e180}
(gdb) p actor
$3 = {tab = 0x7ffff7f721f0, data = 0xc82000e180}
可见,duck与actor的data指针都指向dd
然后是Duck接口的方法集:
(gdb) p duck.tab.inter.mhdr.len
$4 = 2
(gdb) p *(duck.tab.inter.mhdr.array[0].name)
$5 = {str = 0x4ff8c0 “GaGaSpeaking”, len = 12}
(gdb) p *(duck.tab.inter.mhdr.array[1].name)
$6 = {str = 0x4ffb30 “OfficialWalking”, len = 15}
以及其动态类型的具体实现(可以看到,都指向了tanglaoya的具体实现)
(gdb) info symbol duck.tab.fun[0]
main.(*DonaldDuck).GaGaSpeaking in section .text of /home/yugui/go/go
(gdb) info symbol duck.tab.fun[1]
main.(*DonaldDuck).OfficialWalking in section .text of /home/yugui/go/go
再看看Actor的方法集:
(gdb) p actor.tab.inter.mhdr.len
$12 = 1
(gdb) p *(actor.tab.inter.mhdr.array[0].name)
$13 = {str = 0x4fcc10 “MakeFun”, len = 7}
及其动态类型的具体实现
(gdb) info symbol actor.tab.fun[0]
golang 接口的底层实现相关推荐
- golang 接口类型 interface 简介
目录 1. Go 语言与鸭子类型的关系 2. 值接收者和指针接收者的区别 方法 值接收者和指针接收者 两者分别在何时使用 3. iface 和 eface 的区别是什么 4. 接口的动态类型和动态值 ...
- golang 接口类型 interface 简介使用
1. Go 语言与鸭子类型的关系 先直接来看维基百科里的定义: If it looks like a duck, swims like a duck, and quacks like a duck, ...
- GoLang之map底层系列二(浅显学习)
文章目录 GoLang之map底层系列二(浅显学习) 1.map++ 2.map引用传递 3.map不是并发安全 4.map的value为空接口 5.map的value为切片 6.value,ok=m ...
- GoLang之interface底层系列二(类型断言)
文章目录 GoLang之interface底层系列二(类型断言) 1.抽象类型.具体类型 2.断言的作用类型与目标类型 3.空接口.(具体类型) 4.非空接口.(具体类型) 5.空接口.(非空接口) ...
- GoLang之channel底层的数据结构是什么、channel的创建(2)
文章目录 GoLang之channel底层的数据结构是什么.channel的创建(2) 1.数据结构 2.创建 GoLang之channel底层的数据结构是什么.channel的创建(2) 1.数据结 ...
- 雄兔脚扑朔,雌兔眼迷离;双兔傍地走,安能辨我是雄雌?——golang接口的概念
古有花木兰替父从军,安能识我是女郎?今有golang接口隐式实现.对于一个具体的类型,无须声明它实现了哪些接口,只要提供接口所必需的方法即可. 因为golang是我新学的语言,我们先看看其他语言中接口 ...
- golang 接口_「实战」助力数据库开发之接口篇 - Golang 连接 Greenplum
Greenplum 作为一款强大的 HTAP 数据库,针对大多数流行语言都有相应的连接库.大部分均是与 PostgreSQL 采用相同的接口,但是也有部分接口是 Greenplum 专门优化后用于自身 ...
- golang 接口格式
package main import "fmt" type Human struct { name string age int phone string } type Stud ...
- Golang——接口、多态、接口继承与转换、空接口、类型断言
接口是一种规范与标准,只是规定了要做哪些事情.但是具体怎么做,是实现接口的类去做的,接口只是把所有具有共性的方法定义在一起. 接口存在的意义就是用来定义规范,用来做功能的拓展 接口最大的好处是可以实现 ...
最新文章
- Linux Shell中的延时函数
- 熟悉mysql基本数据库操作系统_MySQL数据库的基本操作
- 阿里云ECS服务器连接不上3306端口?
- 【英语学习】【医学】Unit 08 The Cardiovascular System
- static--静态方法与静态成员
- selenium拖动元素java_使用Java在Selenium WebDriver中聚焦元素的正确方法
- pytorch中的nn.LSTM模块参数详解
- android post 提交数据
- hadoop 如何连beeline_impala为hadoop续命
- WPF 微信 MVVM 【续】发送部分QQ表情
- 2050:技术未必会使我们摆脱愚昧,有时正相反(下)
- 软件工程毕设项目 - 基于SSM的房屋租赁系统(含源码+论文)
- Redhat Crash Utility-Ramdump
- Cyclone v器件关键参数
- NShape(开源矢量图形编辑器) 入门(一)
- BigDecimal精度丢失处理
- 论文笔记:Teaching Machine to Read and Comprehend
- uni-app上传图片base64
- PS 一键生成Android各个尺寸的图标
- 爱她就送ta一场樱花雨