1 channel简介

channel是Go语言提供的goroutine间的通信方式。
我们可以使用channel在两个或 多个goroutine之间传递消息。
一个channel只能传递一种类型的值,这个类型需要在声明channel时指定。

2 channel的常用方法

  1. // 创建channel
  2. c := make(chan Type) // 等价于make(chan Type, 0)
  3. c := make(chan Type, capacity) // 带buffer的chan
  4. // 发送
  5. c <- value // 发送value到channel
  6. // 接收
  7. x := <- c // 从channel中取出数据, 并赋值给x
  8. // 关闭, 通道是可以被垃圾回收机制回收的, 关闭通道不是必须的
  9. // 对一个关闭的通道再发送值就会导致panic。
  10. // 对一个关闭的通道进行接收会一直获取值直到通道为空。
  11. // 对一个关闭的并且没有值的通道执行接收操作会得到对应类型的零值。
  12. // 关闭一个已经关闭的通道会导致panic。
  13. close(ch)
  • 无缓冲的channel: 容量=0, 必须有其它运行中的goroutine进行接收才能发送(类似于京东快递员, 会直接送到你家门口)
  • 有缓冲的channel: 容量>=1, 可以由本goroutine来进行发送和接收 (类似于中通快递员, 会送到菜鸟驿站)

3 代码示例

(1) 基本用法

  1. package main
  2. import "fmt"
  3. func main() {
  4. c := make(chan int)
  5. go func() {
  6. defer fmt.Println("goroutine结束")
  7. fmt.Println("goroutine运行中...")
  8. c <- 666
  9. }()
  10. num := <-c
  11. fmt.Println("num:", num)
  12. fmt.Println("main结束")
  13. }

(2) 优雅地从通道循环取值

当通过通道发送有限的数据时,我们可以通过close函数关闭通道来告知从该通道接收值的goroutine停止等待。当通道被关闭时,往该通道发送值会引发panic,从该通道里接收的值一直都是类型零值。那如何判断一个通道是否被关闭了呢?

  1. func main() {
  2. ch1 := make(chan int)
  3. ch2 := make(chan int)
  4. // 开启goroutine将0~100的数发送到ch1中
  5. go func() {
  6. for i := 0; i < 100; i++ {
  7. ch1 <- i
  8. }
  9. close(ch1)
  10. }()
  11. // 开启goroutine从ch1中接收值,并将该值的平方发送到ch2中
  12. go func() {
  13. for {
  14. i, ok := <-ch1 // 通道关闭后再取值ok=false
  15. if !ok {
  16. break
  17. }
  18. ch2 <- i * i
  19. }
  20. close(ch2)
  21. }()
  22. // 在主goroutine中从ch2中接收值打印
  23. for i := range ch2 { // 通道关闭后会退出for range循环
  24. fmt.Println(i)
  25. }
  26. }