今天我们来看下对已经关闭通道进行读写会发生什么情况。
1. 对已关闭通道进行写操作
看下面代码会输出什么结果?
func main() {
ch := make(chan string, 1)
close(ch)
ch <- "hello, world"
fmt.Println(<-ch)
}
输出结果为:
panic: send on closed channel
这个结果无论对于非缓冲通道还是缓冲通道都是一样的,即对已经关闭的通道进行写操作,会触发 panic
。
2. 对已关闭通道进行读操作
对已经关闭的 channel
进行读操作要分为两种情况:
- 已关闭的
channel
没有数据; - 已关闭的
channel
仍然有数据;
2.1 已关闭的 channel 没有数据
看下面代码
func main() {
ch := make(chan int, 1)
close(ch)
// 第一次从通道中获取数据
value, ok := <-ch
fmt.Println(value) // 0
fmt.Println(ok) // false
// 第二次从通道中获取数据
fmt.Printf("<-ch is %v\n", <-ch) // <-ch is 0
fmt.Println(ok) // false
}
从上面代码结果我们可以得出结论,对于已经关闭的 channel
,如果通道内已经没有数据,那么可以不限次数的进行读取操作,但是读到的值是该 channel
类型的零值,也就是上面代码中 int
的零值 0。
如果该通道被声明为 string
类型,那么其零值就为空字符串 ""
。
而从通道返回的第二个值,也就是标志位 ok
,则会一直为 false
。
2.2 已关闭的 channel 仍然有数据
查看下面代码输出结果
func main() {
ch := make(chan int, 3)
ch <- 1
close(ch)
// 第一次从通道中获取数据
value, ok := <-ch
fmt.Println("第一次从通道中获取数据 value", value) // 1
fmt.Println("第一次从通道中获取数据 ok", ok) // true
// 第二次从通道中获取数据
value, ok = <-ch
fmt.Println("第二次从通道中获取数据 value", value) // 0
fmt.Println("第二次从通道中获取数据 ok", ok) // false
}
对于这种情况,从通道里面仍然可以获取到之前存储的数据,同时第二个返回值 ok
的值为 true
, 表示通道里面是有数据的。
但是当通道里面的值被取完时,就和上面 2.1 小节的结果一样了。
3. 对通道操作的总结