Go 通道(channel)

  • Post author:
  • Post category:其他


  • `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 版权协议,转载请附上原文出处链接和本声明。