Go 语言中的管道(channel)是一种特殊的类型,遵循先入先出的规则,保证收发数据的顺序。每一个管道都有具体的类型,也就是声明channel的时候需要为其指定元素类型。
创建管道
管道需要使用make函数初始化之后才能使用。创建管道的格式如下:
代码语言:javascript复制make(chan 管道类型, 缓冲大小)
其中缓冲大小是可选的。
管道操作
创建一个管道
代码语言:javascript复制ch := make(chan int)
发送数据
代码语言:javascript复制ch <- 10
接收数据
代码语言:javascript复制i := <- ch
// 接收数据并忽略结果
<- ch
关闭管道
代码语言:javascript复制close(ch)
管道特点
- 对关闭的管道发送数据会导致panic
- 对关闭的管道能够正常接收数据,直到管道为空
- 从关闭且没有值的管道,能够接收该管道类型对应的零值
- 关闭一个已关闭的管道会导致panic
无缓冲管道
无缓冲的通道只有在有人接收值的时候才能发送值,否则会引发panic。 下面的代码会引发panic。
代码语言:javascript复制package main
func main() {
ch := make(chan int)
ch <- 1
ch <- 2
<-ch
<-ch
close(ch)
}
下面的代码会阻塞而引发panic。
代码语言:javascript复制package main
func main() {
ch := make(chan int)
<-ch
<-ch
ch <- 1
ch <- 2
close(ch)
}
一般使用goroutine接收数据。
代码语言:javascript复制package main
func main() {
ch := make(chan int)
go func() {
<-ch
<-ch
}()
ch <- 1
ch <- 2
close(ch)
}
有缓冲通道
缓冲通道能够暂时储存数据,但当储存的数据超过容量时,依然会引发panic。
代码语言:javascript复制package main
func main() {
ch := make(chan int, 2)
ch <- 1
ch <- 2
<-ch
<-ch
close(ch)
}
优雅的取值
通过for循环和range可以从管道中接收数据,当管道关闭时,自动退出循环。
代码语言:javascript复制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