- `channel`则是`goroutine`之间的通信机制。它可以让一个`goroutine`通过它给另一个`goroutine`发送值信息。
- 每个`channel`都有一个特殊的类型,也就是`channel`可发送数据的类型
- 一个可以发送int类型数据`channel`的一般写为`chan int`
不带缓冲的通道
- 无缓冲`channel`的发送操作将导致发送者`goroutine`阻塞,直到另一个`goroutine`在相同的`channel`上执行了接收操作
- 如果接收操作先发生,那么接收者`goroutine`也将阻塞,直到有另一个`goroutine`在相同的`channel`上执行发送操作
- 当发送的值通过`channel`成功传输后,两个`goroutine`可以继续执行后面的语句
ch := make(chan int)
ch := make(chan int, 0) // 0 也没有缓冲
带缓冲的通道
- 带缓冲的`channel`内部持有一个元素队列
- 队列的最大容量是在调用`make`函数创建`channel`时通过第二个参数指定
ch := make(chan int, 3) // 通道容量为3
通道的发送与接收
- 复制一个通道或者用于函数参数传递时,只是拷贝一个`channel`的引用
- `channel`的零值也是`nil`
// 创建通道
ch := make(chan int)
// 发送
ch <- 10
// 接收
x := <- ch
<- ch // 忽略接收的值
go内置函数
// 内置的cap函数获取channel内部缓冲的容量
fmt.Println(cap(ch)) // '3'
// 内置的len函数获取channel内部缓冲队列中有效元素的个数
fmt.Println(len(ch)) // '2'
通道使用示例
- 如果一个通道在一个协程中发送和接收时,会产生相互等待(死锁)。相当于一个人的一只手,又要去放东西,又要去拿东西,没办法同时完成。
func main() {
var c = make(chan int)
c <- 10 // 放入10到通道
close(c) // 关闭通道
r := <-c // 接收通道中的数据
log.Println(r)
}
- 创建一个子协程(匿名函数),让一个协程发送数据到通道,另外一个协程接收数据
// 通道
func main() {
var c = make(chan int)
// 开启一个子协程
go func() { // 匿名函数
c <- 10
close(c)
}()
r := <-c
log.Println("接收通道数据: ", r)
}
注意:chan是线程安全的,使用时不需要加锁
版权声明:本文为weixin_40123451原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。