疑问1:从已关闭的channel读取数据会怎么样
刚接触go的channel,我在思考一个问题,chan是发送方关闭,还是接收方关闭,如果是发送方关闭,发送方发完数据,就关闭chan,那可能接收方还没接收完数据,读取关闭的信道会怎样?
验证1:有缓冲
package main
import (
"fmt"
"sync"
)
func main() {
ch := make(chan int, 5)
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
fmt.Println("wirte")
for i := 1; i < 5; i++ {
ch <- i
}
close(ch)
fmt.Println("chan close")
wg.Done()
}()
wg.Wait()
fmt.Println("read")
for i := 1; i < 9; i++ {
v, ok := <-ch
fmt.Println(v)
fmt.Println(ok)
}
}
结果

可以看到从已经关闭的chan是读取数据是没有问题的,但读取完chan的数据后再读取会返回false和默认值0
这样又产生一个新问题,接收方如何判断chan已经关闭了呢?
判断返回的是true还是false就可以知道,返回false代表已经关闭
验证2:无缓冲
package main
import (
"fmt"
)
func main() {
ch := make(chan int)
go func() {
fmt.Println("write")
ch <- 1
close(ch)
fmt.Println("chan close")
}()
fmt.Println("read")
for i := 0; i < 5; i++ {
v, ok := <-ch
fmt.Println(v)
fmt.Println(ok)
}
}
结果

结果和有缓冲一样
疑问2:重复关闭chan会怎么样
验证
package main
import (
"fmt"
"sync"
)
func main() {
ch := make(chan int, 5)
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
fmt.Println("wirte")
for i := 1; i < 5; i++ {
ch <- i
}
close(ch)
close(ch)
fmt.Println("chan close")
wg.Done()
}()
wg.Wait()
fmt.Println("read")
for i := 1; i < 9; i++ {
// v, ok := <-ch
fmt.Println(<-ch)
// fmt.Println(ok)
}
}
结果

重复关闭chan会panic
疑问3:向关闭的chan发送信号会怎样
验证
package main
import (
"fmt"
"sync"
)
func main() {
ch := make(chan int, 5)
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
fmt.Println("wirte")
for i := 1; i < 5; i++ {
ch <- i
}
close(ch)
ch <- 5
fmt.Println("chan close")
wg.Done()
}()
wg.Wait()
fmt.Println("stop")
}
结果

本文深入探讨Go语言中Channel的使用细节,包括从已关闭的Channel读取数据的行为、重复关闭Channel的影响以及向关闭的Channel发送信号的结果。通过具体代码示例验证了不同场景下Channel的表现。

被折叠的 条评论
为什么被折叠?



