Go并发编程:Channel和WaitGroup[译]
📅 2023-07-18
并发是Go语言的一个强大特性,它允许开发者编写高效且可扩展的应用程序。在Go中,用于管理并发的两种常用机制是Channel
和WaitGroup
。本文将探讨Channel
和WaitGroup
之间的相似之处和区别,并讨论何时以及如何有效地使用它们。
并发是Go语言的一个强大特性,它允许开发者编写高效且可扩展的应用程序。在Go中,用于管理并发的两种常用机制是Channel
和WaitGroup
。本文将探讨Channel
和WaitGroup
之间的相似之处和区别,并讨论何时以及如何有效地使用它们。
今天继续学习Go 1.18引入的泛型,每天利用几分钟的时间来学习,慢慢积累。
前两天学习了在Go中如何定义泛型函数,并学习了Go泛型中的类型约束(Type Constrant)的概念,今天通过参考Go官方的泛型技术提案文档,简单整理一下Go泛型的基本语法。
Go的泛型指的是在Go的类型声明和函数声明中增加可选的类型参数
。类型参数要受到类型约束,Go使用嵌入额外元素的接口类型来定义类型约束
,类型约束定义了一组满足约束的类型集(Type Set
)。
今天继续学习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]
就是类型约束。
今天开始,来学习Go 1.18引入的泛型,我们将以Go官方的泛型教程为资料,每天利用几分钟的时间来学习,慢慢积累。
很多编程语言都支持泛型的特性,泛型是对具体类型或属性的抽象替代,可以实现在编写代码和编译代码时无需知道其在运行时具体类型的特性。
根据Go官方的泛型教程,我们将先实现两个简单的未使用泛型的函数,随后将定义一个泛型函数实现相同的逻辑。
...Go 1.18这个大型版本终于发布了,包括新功能、性能改进以及对语言的最大改变。 官方博客称Go 1.18的部分设计甚至开始于10年前首次发布Go的时候。具体来说,Go 1.18包含以下几大特性:
我在开发机上上的Go版本管理策略如下: 使用MacOS Homebrew安装的go作为主要版本, 因为Go的Homebrew Formula版本更新会延迟Go官方的发布。
所以为了体验Go新版本的特性或者同时在本地保留多个Go的版本,会使用Go Wrapper程序golang.org/dl
下载对应版本的Go Wrapper,再使用Wrapper下载安装对应的Go。
Go语言中的切片slice的底层数据结构是数组,这是即使是Go的初学者都了解的。
前面我们学习了string
类型在运行时由reflect.StringHeader
表示,StringHeader可以理解为string在运行时的"描述符",StringHeader由Data和Len两个字段组成,Data是指向string底层byte数组的指针,Len是string的长度。
前面在学习Go程序进程的内存布局时,分析了一个Go程序在Linux下ELF文件格式经过简化后大致如下图所示:
Go二进制文件ELF主要有这几个section组成: .text
, .rodata
, .data
, .noptrdata
, .bss
, .noptrbss
。
.rodata
中存放的是常量数据,程序中的字面量在编译时会被放到这个section中,那么字符串字面量也将放到这个section中。
在执行程序时,ELF文件被加载到内存中,相同权限的Section会被对应到一个Segment中,大致是下图的内存加载结构:
作为一个Gopher在刚开始学习channel的时候,一定见过以下关于关闭channel会发生什么情况
的总结:
本节将学习关闭channel,即close(ch)
的内部实现。关闭channel实际上调用的是runtime.closechan
这个函数。
本节将学习从channel中接收数据的内部实现。
在Go中从channel中接收数据有两种方式:
1v <- ch
2v, ok <- ch
使用v <- ch
从channel中接收数据时,会调用runtime.chanrecv1
,chanrecv1
调用了runtime.chanrecv
。
前面学习了channel的底层数据结构hchan以及hchan是如何被创建的。
使用类似ch <- 3
往channel中发送数据时,会调用runtime.chansend1
,chansend1
调用了chansend
,本节将主要学习runtime.chansend
这个函数。