注意
:通道首先要通过make函数来初始化,初始化之后才可以执行写入和读取操作。此外还分为【有缓存通道
】和【无缓存通道
】,make函数第二个参数大于1,表示有缓存;make函数的第二个参数的类型为整型,在使用make函数初始化通道时,缓存必须大于1。不可以是0。
首先看一下通道在一个协程中的例子
发送操作阻塞
package main
func main() {
var ch chan struct{}
//ch = make(chan struct{}, 1)
ch <- struct{}{}
<-ch
}
运行结果
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send (nil chan)]:
main.main()
发送(写入)操作阻塞,此外通道没有初始化,nil chan
表示通道没有初始化。
接收操作阻塞
package main
func main() {
var ch chan struct{}
ch = make(chan struct{}, 1)
<-ch //程序到这一行直接阻塞,即使有缓存也不行,因为通道为空,读不到数据。
ch <- struct{}{}
}
运行结果
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
读取(接收)操作阻塞,即使有缓存也会继续阻塞,因为通道为空,读取不到数据,后面的代码不会执行了。
编译通过
package main
func main() {
var ch chan struct{}
ch = make(chan struct{}, 1)
ch <- struct{}{}
<-ch
}
因为有缓存,所以可以往通道里写入数据,即使把最后一行注释掉,程序也可以正常运行,不会阻塞。
分别在两个协程中进行读取(接收)和写入(发送),一边读取,一边写入
读取写入均阻塞
package main
func main() {
var ch chan struct{}
go func() {
ch <- struct{}{}
}()
<-ch
}
运行结果
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive (nil chan)]:
main.main()
goroutine 4 [chan send (nil chan)]:
main.main.func1(0x0)
created by main.main
虽然程序可以一直执行到最后一行,但是因为通道没有初始化,所以两边都阻塞。
接收操作阻塞
package main
func main() {
var ch chan struct{}
ch = make(chan struct{})
<-ch
go func() {
ch <- struct{}{}
}()
}
运行结果
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
主函数接收操作首先阻塞,后面的代码不会执行了,即使通道有缓存也会阻塞,因为通道为空,读取不到数据。
发送和接收均阻塞
package main
func main() {
var ch chan struct{}
go func() {
<-ch
}()
ch <- struct{}{} //程序一直可以执行到这一行,但是通道没有初始化,所以两边都阻塞。
}
运行结果
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send (nil chan)]:
main.main()
goroutine 17 [chan receive (nil chan)]:
main.main.func1(0x0)
created by main.main
虽然程序一直可以执行到最后一行,但是因为通道没有初始化,所以两边都阻塞,这个例子是主函数里边写入,子协程里边读取,与上一个两边均阻塞的正好反过来。
发送操作阻塞
package main
func main() {
var ch chan struct{}
ch = make(chan struct{})
ch <- struct{}{} //函数执行到这一行直接阻塞,不管有无缓存,都会阻塞
go func() {
<-ch
}()
}
运行结果
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
主函数发送(写入)操作先阻塞了,后面的代码不会执行了,不管通道有无缓存,程序都已经阻塞不会再继续往下执行了。
另一个协程准备好了接收数据
package main
func main() {
var ch chan struct{}
ch = make(chan struct{})
go func() {
<-ch
}()
ch <- struct{}{} //因为另一个协程已经准备好了接收,所以通道无缓存,程序也可以运行
}
因为另一个协程准备好了读取数据,所以即使通道无缓存也可以正常运行。
另一个协程往通道中写入了数据
package main
func main() {
var ch chan struct{}
ch = make(chan struct{})
go func() {
ch <- struct{}{}
}()
<-ch //程序一直可以执行到这一行,而另一个协程准备好了往通道里写入了数据,所以即使通道无缓存,也可以正常运行。
}
因为另一个协程已经准备好了往通道里写入数据,所以通道无缓存也不会阻塞。