继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

【九月打卡】第8天 go的接口

慕九州9237533
关注TA
已关注
手记 43
粉丝 2
获赞 4

课程名称:深入Go底层原理,重写Redis中间件实战


课程章节:4-9 ,4-10接口--隐式更好还是显式更好

课程讲师:Moody


课程内容:


※ go 接口底层

△ 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是动态类型已经实现的接口方法的调用地址数据

fun   [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter.

}


△ 如果是空接口,也就是interface{} 则底层是 eface

type eface struct {

_type *_type

data  unsafe.Pointer

}

※ 结构体和指针实现接口

http://img4.mukewang.com/632048fb000175a019540403.jpg

http://img3.mukewang.com/63205e7200019f0014610995.jpg

这是因为,在使用结构体实现一个方法的时候,go自动的也用结构体的指针实现了一个方法。但是如果你只是使用指针实现,go不会再用结构体实现一遍。

※ 当且仅当两个接口类型变量的类型信息相同,且数据指针所指向的数据相同时,两个接口类型才算相等,==为true

※通过println可输出接口类型变量的两部分指针变量的值

※ convT2E 是将任意类型转换为eface,而convT2I是将任意类型转换为iface。主要思路就是根据传入的类型信息分配一块内存空间,并将elem指向的数据复制到这个新分配的内存空间,最后传入的类型信息作为返回值结构体中的类型信息,返回值结构中的数据指针指向新分配的那个内存空间。

※那么go是如何知道传入的T的类型的,这是go的编译器的工作,编译器知道每个要转换为接口类型变量的动态类型变量的类型(反射) 具体源码在  /src/cmd/compile/internal/gc/walk.go -> func walkexpr()


从上面就可以看出,为了处理空接口,是需要额外开辟一个内存空间的,等于说元数据成为了2被的内存空间,这也是大多数的人在呼吁尽量少的使用interface{}。或者,一些github的项目宣称自己没有使用interface的。毕竟内存不仅仅是分配一块出来,还容易逃逸。


课程收获:

明白了go的"泛型" interface的一些底层原理


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP