channel
是Golang
在语言层面提供的goroutine
间的通信方式,比Unix
管道更易用也更轻便。channel
主要用于进程内各goroutine
间通信,如果需要跨进程通信,建议使用分布式系统的方法来解决。
如果说 goroutine
是 Go语言程序的并发体的话,那么 channels
就是它们之间的通信机制。它可以让一个 goroutine
通过它给另一个 goroutine
发送值信息。每个 channel
都有一个特殊的类型,也就是 channel
可发送数据的类型。一个可以发送 int 类型数据的 channel 一般写为 chan int
。
Go语言提倡使用通信的方法代替共享内存,当一个资源需要在 goroutine
之间共享时,channel
在 goroutine
之间架起了一个管道,并提供了确保同步交换数据的机制。声明channel
时,需要指定将要被共享的数据的类型。可以通过channel
共享内置类型、命名类型、结构类型和引用类型的值或者指针。
核心包括一个 lock 控制并发, 等待发送的队列, 等待接收的队列, 队列大小, 队列元素指针, 是否关闭标识。
通信的方法就是使用通道(channel),如下图所示。
以上5个特性是死东西,也可以通过口诀来记忆:“空读写阻塞,写关闭异常,读关闭空零”。
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int, 1000)
go func() {
for i := 0; i < 10; i++ {
ch <- i
}
}()
go func() {
for {
a, ok := <-ch
if !ok {
fmt.Println("close")
return
}
fmt.Println("a: ", a)
}
}()
close(ch)
fmt.Println("ok")
time.Sleep(time.Second * 100)
}
15字口诀:“空读写阻塞,写关闭异常,读关闭空零”,往已经关闭的channel写入数据会panic的。因为main在开辟完两个goroutine之后,立刻关闭了ch, 结果:
ok
close
panic: send on closed channel
声明一个 channel
写入数据,更新 sendx 和 recvx
写满数据,更新 sendx 和 recvx
读取一个数据,更新 sendx 和 recvx