疑问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")
}