GO成神之路: 详解channel(一)|Go主题月

1,318 阅读1分钟

channel是什么

channel字Go中主要用来协程间传递数据,当然除了协程之外我们也可以使用全局变量,但是使用全局变量时,我们需要另外考虑协程安全的问题,而channel就是用来解决协程安全问题的一种实现方案,channel的实现其实也是通过Go提供的协程同步api实现的。

编译后的channel是什么样子的

channel其实是类似于订阅发布系统中的频道或主题的概念,既然是订阅发布系统,那自然离不开发布者和订阅者,chan的内部是通过runtime.sendchan1runtime.chanrecv1两个函数来实现发布和订阅的,而我们编码中经常用到的<-只是Go给我提供的语法糖。
具体为什么是runtime.sendchan1runtime.chanrecv1这两个看起来很奇怪的函数名,我们可以从下面代码的汇编指令中找到答案:

package main

import "log"

func main() {
	c := make(chan int)
	go func() {
		c <- 1
	}()
	a := <-c
	log.Println(a)
}

使用go tool compile -S main.go >> main.txt命令来查看Go代码的汇编指令,如下:

# 定义chan int类型
0x0040 00064 (main.go:6)	CALL	runtime.makechan(SB)
...
# <-c 被编译后对应runtime.chanrecv1
0x0083 00131 (main.go:10)	CALL	runtime.chanrecv1(SB) 
...
# c<-1 被编译后对应runtime.chansend1
0x0039 00057 (main.go:8)	CALL	runtime.chansend1(SB)

本段Go的汇编指令,这里只挑选了重要的几个进行说明,如果想查看完整的,请按上面命令自行生成

上面我们通过一个简单的例子编译后的汇编指令,展示了channel的实现大致包涵哪些函数,比如channel应该至少包涵runtime.sendchan1runtime.chanrecv1两个函数。通过这两个函数作为切入点,后续我们将具体分析channel的源码,并详细介绍channle的实现。