为了账号安全,请及时绑定邮箱和手机立即绑定

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

标签:
Go

课程名称:深入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

}

※ 结构体和指针实现接口

https://img1.sycdn.imooc.com//632048fb000175a019540403.jpg

https://img1.sycdn.imooc.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的一些底层原理


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消