版权属于:
桑帅东的博客
作品采用:
《
署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)
》许可协议授权
1. 什么是channel?
channel的中文意思就是通道。在go中channel主要是用于协程之间的通信。
channel可以在同一时间保证只有一个携程在操作,从而避免了数据的竞争,实现的同步操作。
2. channel使用
在go中,channel需要使用make函数进行内存分配。可以使用make函数,指定缓冲区的大小。
ch := make(chan int,6)
如果不指定缓冲区,则成为无缓冲区通道。该通道只有sender和receiver都准备好时,才能进行通信。
func pump(ch chan int) {
for i := 1;;i++ {
ch <- i
}
}
ch1 := make(chan int) // 无缓冲通道
go pump(ch1)
以上程序没有receiver,程序会报错。因为通道是没有缓冲区的。当sender发送一个数据的时候,必须有receiver接收数据,这样sender才能继续发送数据。类似于生产者->消费者问题
func pump(ch chan int) {
for i := 1;;i++ {
ch <- i
}
}
ch1 := make(chan int) // 无缓冲通道
go pump(ch1)
fmt.Println(<-ch1) // 这里只接收的到发送的第一个数据1。
发送、接收数据
根据 <- 的流向,来判断是向通道发送数据,还是读取通道中的数据
ch := make(chan int,1)
ch <- 10 // 向ch通道发送数据
ch = make(chan int,1)
ch <- 10
x := <- ch // 读取ch通道中的数据,并复制给x变量。
注意:
不能向已经满了的通道发送数据,否则会造成阻塞。
ch = make(chan int,2)
ch <- 10
ch <- 20
ch <- 30 // 通道缓冲区大小为2,已满,不能再发送数据
该错误告诉我们,所有的线程都已经休眠。则没有一个线程在运行,发生死锁。
关闭通道
close(ch) // 使用该方法关闭通道
只有发送者可以关闭通道。 关闭的通道,在无数据的情况下,会返回false。否则是true。
读取通道中的数据
for range 可以读取通道中的数据,直到通道关闭
for range
例如:
for v := range ch1 {
fmt.Printf("%v",v)
}
3. 单通道
顾名思义,就是单向的通道,也就是只能接受或者发送的通道。
只能接收
var ch <- chan int
只能发送
var ch chan <- int
4. select
不同于switch,select只能用于io操作,一般配合channel使用。
例如:
select {
case msg1 := <-c1:
fmt.Println("c1 received:",msg1)
case msg2 := <-c2:
fmt.Println("c2 received",msg2)
default:
fmt.Println("No data received")
}
以上例子中,只要一个通道里有数据,就会执行case。
如果没有匹配的case,且没有default语句。那么select会阻塞,直到某一case可以执行
与switch的主要区别:
switch的case是顺序匹配执行的。而select是随机执行的。
select中表达式必须是和通道有关的操作。
评论