问题
对已经关闭的的 chan 进行读写,会怎么样?为什么?
怎么答
读已经关闭的 chan 能一直读到东西,但是读到的内容根据通道内关闭前是否有元素而不同。
如果 chan 关闭前,buffer 内有元素还未读 , 会正确读到 chan 内的值,且返回的第二个 bool 值(是否读成功)为 true。
如果 chan 关闭前,buffer 内有元素已经被读完,chan 内无值,接下来所有接收的值都会非阻塞直接成功,返回 channel 元素的零值,但是第二个 bool 值一直为 false。
写已经关闭的 chan 会 panic
举例
1. 写已经关闭的 chan
代码语言:go复制package main
func main() {
ch := make(chan int, 3)
close(ch)
ch <- 1
}
panic: send on closed channel
goroutine 1 [running]:
main.main()
D:/goproject/src/github.com/leetcode/test.go:6 0x452. 读已经关闭的 chan
进程 已完成,退出代码为 2
2. 读已经关闭的 chan
代码语言:go复制package main
import "fmt"
func main() {
fmt.Println("以下是数值chan")
c1 := make(chan int, 3)
c1 <- 1
close(c1)
num, ok := <-c1
fmt.Printf("num=%v,ok=%v", num, ok)
num1, ok1 := <-c1
fmt.Printf("num1=%v,ok1=%v", num1, ok1)
num2, ok2 := <-c1
fmt.Printf("num2=%v,ok2=%v", num2, ok2)
fmt.Println("以下是字符串的chan")
c2 := make(chan string, 3)
c2 <- "abc"
close(c2)
str, ok := <-c2
fmt.Printf("str=%v,ok=%v", str, ok)
str1, ok1 := <-c2
fmt.Printf("str1=%v,ok1=%v", str1, ok1)
str2, ok2 := <-c2
fmt.Printf("str2=%v,ok2=%v", str2, ok2)
}
num=1,ok=true
num1=0,ok1=false
num2=0,ok2=false
str="abc",ok=true
str1="",ok1=false
str2="",ok2=false
多问一句
1. 为什么写已经关闭的 chan 就会 panic 呢?
代码语言:go复制//src/runtime/chan.go/chansend
if c.closed != 0 {
unlock(&c.lock)
panic(plainError("send on closed channel"))
}
当 c.closed != 0 则为通道关闭,此时执行写,源码提示直接 panic,输出的内容就是上面提到的 "send on closed channel"。