内容简介:Go的interface源码在Golang源码的Go的interface是由两种类型来实现的:而
Go的interface源码在Golang源码的 runtime
目录中。 Go在不同版本之间的interface结构可能会有所不同,但是,整体的结构是不会改变的,此文章用的 Go 版本是1.11。
Go的interface是由两种类型来实现的: iface
和 eface
。 其中, iface
表示的是包含方法的interface,例如:
type Person interface { Print() } 复制代码
而 eface
代表的是不包含方法的interface,即
type Person interface {} 复制代码
或者
var person interface{} = xxxx实体 复制代码
eface
eface
的具体结构是:
_type
,一个是数据信息。 其中,
_type
可以认为是Go语言中所有类型的公共描述,Go语言中几乎所有的数据结构都可以抽象成
_type
,是所有类型的表现,可以说是万能类型,
data
是指向具体数据的指针。
type
的具体代码为:
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
的整体结构是:
对于没有方法的interface赋值后的内部结构是怎样的呢? 可以先看段代码:
import ( "fmt" "strconv" ) type Binary uint64 func main() { b := Binary(200) any := (interface{})(b) fmt.Println(any) } 复制代码
输出200,赋值后的结构图是这样的:
对于将不同类型转化成type
万能结构的方法,是运行时的
convT2E
方法,在
runtime
包中。 以上,是对于没有方法的接口说明。 对于包含方法的函数,用到的是另外的一种结构,叫
iface
iface
所有包含方法的接口,都会使用 iface
结构。包含方法的接口就是一下这种最常见,最普通的接口:
type Person interface { Print() } 复制代码
iface
的源代码是:
type iface struct { tab *itab data unsafe.Pointer } 复制代码
iface
的具体结构是:
itab
是 iface
不同于 eface
比较关键的数据结构。其可包含两部分:一部分是确定唯一的包含方法的interface的具体结构类型,一部分是指向具体方法集的指针。 具体结构为:
itab
的源代码是:
type itab struct { inter *interfacetype //此属性用于定位到具体interface _type *_type //此属性用于定位到具体interface hash uint32 // copy of _type.hash. Used for type switches. _ [4]byte fun [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter. } 复制代码
属性 interfacetype
类似于 _type
,其作用就是interface的公共描述,类似的还有 maptype
、 arraytype
、 chantype
...其都是各个结构的公共描述,可以理解为一种外在的表现信息。 interfacetype
源码如下:
type interfacetype struct { typ _type pkgpath name mhdr []imethod } type imethod struct { name nameOff ityp typeOff } 复制代码
iface
的整体结构为:
对于含有方法的interface赋值后的内部结构是怎样的呢? 一下代码运行后
package main import ( "fmt" "strconv" ) type Binary uint64 func (i Binary) String() string { return strconv.FormatUint(i.Get(), 10) } func (i Binary) Get() uint64 { return uint64(i) } func main() { b := Binary(200) any := fmt.Stringer(b) fmt.Println(any) } 复制代码
首先,要知道代码运行结果为:200。 其次,了解到 fmt.Stringer
是一个包含 String
方法的接口。
type Stringer interface { String() string } 复制代码
最后,赋值后接口 Stringer
的内部结构为:
对于将不同类型转化成itable中 type(Binary)
的方法,是运行时的 convT2I
方法,在 runtime
包中。
参考文献: 《Go in action》 research.swtch.com/interfaces juejin.im/entry/5a7d0…
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Go语言interface底层实现
- Go语言interface底层实现
- 解剖Go语言map底层实现
- Go语言map的底层实现
- 12 Go语言map底层浅析
- avue 1.5.2 优化大量底层代码,crud 和 form 底层公用
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
深入应用C++11
祁宇 / 机械工业出版社 / 2015-5 / 79
在StackOverflow的最近一次世界性调查中,C++11在所有的编程语言中排名第二, C++11受到程序员的追捧是毫不意外的,因为它就像C++之父Bjarne Stroustrup说的:它看起来就像一门新的语言。C++11新增加了相当多的现代编程语言的特性,相比C++98/03,它在生产力、安全性、性能和易用性上都有了大幅提高。比如auto和decltype让我们从书写冗长的类型和繁琐的类型......一起来看看 《深入应用C++11》 这本书的介绍吧!