2022-03-19
今天继续学习Go 1.18引入的泛型,每天利用几分钟的时间来学习,慢慢积累。
前两天学习了在Go中如何定义泛型函数,并学习了Go泛型中的类型约束(Type Constrant)的概念,今天通过参考Go官方的泛型技术提案文档,简单整理一下Go泛型的基本语法。
Go的泛型指的是在Go的类型声明和函数声明中增加可选的类型参数
。类型参数要受到类型约束,Go使用嵌入额外元素的接口类型来定义类型约束
,类型约束定义了一组满足约束的类型集(Type Set
)。
...2022-03-18
今天继续学习Go 1.18引入的泛型,我们将以Go官方的泛型教程为资料,每天利用几分钟的时间来学习,慢慢积累。
昨天我们定义了一个泛型函数,代码如下:
1// SumIntsOrFloats sums the values of map m. It supports both int64 and float64
2// as types for map values.
3func SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) V {
4 var s V
5 for _, v := range m {
6 s += v
7 }
8 return s
9}
在定义泛型函数时,需要为泛型参数指定 类型约束(type constraint) 来限制泛型参数类型的范围。
SumIntsOrFloats
函数名称后边中括号的内容[K comparable, V int64 | float64]
就是类型约束。
...2022-03-17
今天开始,来学习Go 1.18引入的泛型,我们将以Go官方的泛型教程为资料,每天利用几分钟的时间来学习,慢慢积累。
很多编程语言都支持泛型的特性,泛型是对具体类型或属性的抽象替代,可以实现在编写代码和编译代码时无需知道其在运行时具体类型的特性。
根据Go官方的泛型教程,我们将先实现两个简单的未使用泛型的函数,随后将定义一个泛型函数实现相同的逻辑。
...2022-03-16
Go 1.18这个大型版本终于发布了,包括新功能、性能改进以及对语言的最大改变。
官方博客称Go 1.18的部分设计甚至开始于10年前首次发布Go的时候。具体来说,Go 1.18包含以下几大特性:
- 泛型(Generics): Go 1.18开始引入了泛型的支持。现在我们可以从Go官方的泛型教程来学习这个新特性,另外在Go 1.18的发布说明中也有很多关于泛型的使用细节。
- 模糊测试(Fuzzing): Go成为第一个将模糊测试完全集成到其标准工具链中的主要语言。可以从Go官方的Fuzzing教程中开始学习。
- 工作空间(Workspaces): Go Module已经被广泛使用,目前Gopher在使用Go Module时最常见的挑战是如何应对在多个Module间工作。Go 1.18通过新的Go工作空间模式解决了这一问题。
- 20%性能提升: AppleM1、ARM64和PowerPC64用户会很开心! 因为Go 1.17的寄存器ABI调用约定扩展到这些架构,Go 1.18提供了高达20%的性能改进。
安装Go 1.18
#
我在开发机上上的Go版本管理策略如下: 使用MacOS Homebrew安装的go作为主要版本, 因为Go的Homebrew Formula版本更新会延迟Go官方的发布。
所以为了体验Go新版本的特性或者同时在本地保留多个Go的版本,会使用Go Wrapper程序golang.org/dl
下载对应版本的Go Wrapper,再使用Wrapper下载安装对应的Go。
...2021-11-16
Go语言中的切片slice的底层数据结构是数组,这是即使是Go的初学者都了解的。
前面我们学习了string
类型在运行时由reflect.StringHeader
表示,StringHeader可以理解为string在运行时的"描述符",StringHeader由Data和Len两个字段组成,Data是指向string底层byte数组的指针,Len是string的长度。
...2021-11-15
前面在学习Go程序进程的内存布局时,分析了一个Go程序在Linux下ELF文件格式经过简化后大致如下图所示:
Go二进制文件ELF主要有这几个section组成: .text
, .rodata
, .data
, .noptrdata
, .bss
, .noptrbss
。
.rodata
中存放的是常量数据,程序中的字面量在编译时会被放到这个section中,那么字符串字面量也将放到这个section中。
在执行程序时,ELF文件被加载到内存中,相同权限的Section会被对应到一个Segment中,大致是下图的内存加载结构:
...2021-11-05
作为一个Gopher在刚开始学习channel的时候,一定见过以下关于关闭channel会发生什么情况
的总结:
- 关闭一个值为nil的channel将会panic
- 关闭一个已经关闭的channel将会panic
- 向一个已经关闭的channel发送数据会panic
本节将学习关闭channel,即close(ch)
的内部实现。关闭channel实际上调用的是runtime.closechan
这个函数。
...2021-11-03
本节将学习从channel中接收数据的内部实现。
在Go中从channel中接收数据有两种方式:
使用v <- ch
从channel中接收数据时,会调用runtime.chanrecv1
,chanrecv1
调用了runtime.chanrecv
。
...2021-11-02
前面学习了channel的底层数据结构hchan以及hchan是如何被创建的。
使用类似ch <- 3
往channel中发送数据时,会调用runtime.chansend1
,chansend1
调用了chansend
,本节将主要学习runtime.chansend
这个函数。
...2021-11-01
channel是Go语言核心数据结构之一。Go提供了CSP(通信顺序进程Communicating sequential processes)的并发模型,关于Go并发的那句经典的谚语不要通过共享内存的方式进行通信,而是应该通过通信的方式共享内存
,goroutine之间的通信通过channel来完成。
本节将通过阅读源码(Go 1.17.2)了解Go语言中channel的数据结构,以及channel是如何被创建的。
...