golang 类型系统

类型系统



类型系统

如果我们自定义一个结构体类型T,并给它关联一个方法F1。我们知道变量t的内存布局只包含一个字符串变量,那它和F1之间怎样建立关联?

type T struct {
    name string
}
func (t T) F1() {
    fmt.Println(t.name)
}  
func main() {
    t := T{name: "eggo"}
    t.F1()
}

由于编译阶段,编译器知道每种类型定义了哪些方法,之前我们也介绍过,方法本质上就是函数,只不过在调用时,接收者会作为第一个参数传入。所以通过变量t来调用方法F1时,编译器自然知道要调用哪个函数。

在这里插入图片描述

但是到了执行阶段,为了支持反射、接口动态派发、类型断言这些语言特性或机制,编译器会给每种类型生成对应的类型描述信息写入可执行文件,这些类型描述信息就是“类型元数据”。

在Go语言里,int、float、string、slice、map、interface等属于内置类型(built-in),而我们自己通过下面这三种方式定义的类型,都属于自定义类型。

type T1 int

type T2 struct {
    name string
}
type T3 interface {
    F1()
}

给内置类型定义方法是不被允许的,而接口类型是无效的方法接收者,所以我们只能给上面第一、第二种形式的自定义类型定义方法。

数据类型虽然很多,但是不管是内置类型还是自定义类型,它的“类型元数据”都是全局唯一的。这些类型元数据共同构成了Go语言的类型系统。

在这里插入图片描述

下面就把类型元数据展开,看看里面究竟是什么结构,有什么内容。

内置类型元数据

像类型名称,大小,对齐边界,是否为自定义类型等信息,是每个类型元数据都要记录的。所以被放到了runtime._type结构体中,作为每个类型元数据的Header。

type _type struct {
    size       uintptr
    ptrdata    uintptr
    hash       uint32
    tflag      tflag
    align      uint8
    fieldalign uint8
    kind       uint8
    alg        *typeAlg
    gcdata     *byte
    str        nameOff
    ptrToThis  typeOff
}

在_type之后存储的是各类型额外需要描述的信息,例如slice的类型元数据在_type结构体后面,记录着一个*_type,指向其存储的元素的类型元数据。

type slicetype struct {
    typ   _type
    elem  *_type
}

如果是存储string的slice类型,这个指针就指向string类型的元数据。

在这里插入图片描述

再看看指针类型的元数据,它在_type后面也额外存储了一个*_type,指向指针类型指向的那个类型的元数据。

type ptrtype struct {
    typ   _type
    elem  *_type
}

在这里插入图片描述

内置类型的元数据都是这样的结构,可以到runtime包下的type.go查看struct、map等类型的元数据信息。

自定义类型元数据

然而如果是自定义类型,这后面还会有一个uncommontype结构体。

type uncommontype struct {
    pkgpath nameOff
    mcount  uint16 
    _       uint16 // unused
    moff    uint32 
}
  • pkgpath 记录类型所在的包路径;
  • mcount 记录了该类型关联到多少个方法;
  • moff 记录的是这些方法的元数据组成的数组,相对于这个uncommontype结构体偏移了多少字节。方法元数据结构如下:
type method struct {
    name nameOff
    mtyp typeOff
    ifn  textOff
    tfn  textOff
}

例如,我们基于[]string定义一个新类型myslice,它就是一个自定义类型,可以给它定义两个方法Len和Cap。

myslice的类型元数据中,首先是slicetype类型描述信息,然后在后面加上uncommontype结构体。注意通过uncommontype这里记录的信息,我们就可以找到myslice的方法元数据列表了。

在这里插入图片描述

alias

现在我们可以利用类型元数据来描述下面这两种写法的不同了:

type MyType1 = int32
type MyType2 int32

MyType1这种写法,叫做给类型int32取别名,实际上MyType1和int32会关联到同一个类型元数据,属于同一种类型。rune和int32就是这样的关系。

在这里插入图片描述

而MyType2这种写法,属于基于已有类型创建新类型,MyType2会自立门户,拥有自己的类型元数据,即使MyType2相对于int32来说没有做任何改变,它们两个对应的类型元数据也已经不同了。

在这里插入图片描述

既然每种类型都有唯一对应的类型元数据,而类型定义的方法能通过类型元数据找到,那么,很多问题就变得好解释了,例如接下来的“接口”。

文章转载于:

https://mp.weixin.qq.com/s/qQsLP5o7U8AG_phzGzbjJg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Golang是一种高效的编程语言,因此使用它来开发博客系统是一个不错的选择。首先,我们可以利用Golang的并发特性来提高博客系统的性能,实现更高的并发访问量和更快的响应速度。其次,Golang的内置网络库和丰富的第三方库可以帮助我们轻松实现博客系统的各种功能,如用户认证、文章管理、评论系统等。另外,Golang还提供了良好的标准库和极低的内存消耗,可以有效地减少系统的资源占用,提高系统的稳定性和可靠性。 对于博客系统的前端开发,我们可以选择使用Golang的Web框架,比如Gin或者Beego,这些框架都提供了强大的路由和中间件功能,可以帮助我们快速搭建出美观、高效的界面。同时,Golang还支持模板引擎,我们可以利用模板引擎来实现页面的动态渲染和数据展示。 在数据库方面,Golang也有丰富的支持。我们可以选择使用Golang的SQL库来操作数据库,也可以使用ORM框架来简化数据库的操作流程。另外,Golang还支持各种类型的数据库,包括MySQL、PostgreSQL、MongoDB等,可以根据实际需求选择合适的数据库。 总之,利用Golang来开发博客系统,可以获得高性能、高可靠性和高效率的优势,是一个非常值得考虑的选择。同时,Golang社区也非常活跃,有丰富的资源和优秀的开源项目可以借鉴和使用。希望有更多的开发者能够利用Golang来开发出更加强大和优秀的博客系统

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值