Go 语言中的管道(channel)是一种特殊的类型,遵循先入先出的规则,保证收发数据的顺序。每一个管道都有具体的类型,也就是声明channel的时候需要为其指定元素类型

创建管道

管道需要使用make函数初始化之后才能使用。创建管道的格式如下:

make(chan 管道类型, 缓冲大小)

其中缓冲大小是可选的。

管道操作

创建一个管道

ch := make(chan int)

发送数据

ch <- 10

接收数据

i := <- ch
//  接收数据并忽略结果
<- ch

关闭管道

close(ch)

管道特点

  • 对关闭的管道发送数据会导致panic
  • 对关闭的管道能够正常接收数据,直到管道为空
  • 从关闭且没有值的管道,能够接收该管道类型对应的零值
  • 关闭一个已关闭的管道会导致panic

无缓冲管道

无缓冲的通道只有在有人接收值的时候才能发送值,否则会引发panic。 下面的代码会引发panic。

package main
 
func main() {
	ch := make(chan int)
	ch <- 1
	ch <- 2
	<-ch
	<-ch
	close(ch)
}

下面的代码会阻塞而引发panic。

package main
 
func main() {
	ch := make(chan int)
	<-ch
	<-ch
	ch <- 1
	ch <- 2
	close(ch)
}

一般使用goroutine接收数据。

package main
 
func main() {
	ch := make(chan int)
	go func() {
		<-ch
		<-ch
	}()
	ch <- 1
	ch <- 2
	close(ch)
}

有缓冲通道

缓冲通道能够暂时储存数据,但当储存的数据超过容量时,依然会引发panic。

package main
 
func main() {
	ch := make(chan int, 2)
	ch <- 1
	ch <- 2
	<-ch
	<-ch
	close(ch)
}

优雅的取值

通过for循环和range可以从管道中接收数据,当管道关闭时,自动退出循环。

package main
 
import "fmt"
 
func main() {
	ch := make(chan int)
	go func() {
		for i := range ch {
			fmt.Println(i)
		}
	}()
	ch <- 1
	ch <- 2
	close(ch)
}

单向管道

普通管道:chan int 只能发送的管道:chan <- int 只能接收的管道:<- chan