- for select时,如果通道已经关闭会怎么样?如果只有⼀个case呢?
先说下猜想:通道虽然关闭了,但是还是可以从里面取出数据的,所以并没有什么影响,如果只有一个case,而这个case 如果还没有准备好会一直阻塞,下面来举个例子来验证下我们的猜想:
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int)
go func(){
for {
select {
case a:= <- ch
fmt.Println("a:",a)
}
}
}()
ch <- 1
close(ch)
time.Sleep(time.Second)
fmt.Println("main结束")
}
这段代码for select 会持续打印1秒钟,然后程序退出,下面看下执行结果:

所以从执行结果来看即使channel 关闭了也不会太影响,不过我们可以在读取数据的时间判断channel 是否关闭,如果已经关闭退出循环即可,下面修改下上面的代码:
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int)
go func(){
for {
select {
case a,ok := <- ch
if !ok {
return
}
fmt.Println("a:",a)
}
}
}()
ch <- 1
close(ch)
time.Sleep(time.Second)
fmt.Println("main结束")
}
另外,如果select case 只有一个case,如果io事件一直没有准备好,那么会导致程序卡死,这个时候我们可以设置一个超时时间:
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int)
go func(){
for {
select {
case a,ok := <- ch
if !ok {
return
}
fmt.Println("a:",a)
case <-time.After(5 * time.Second):
fmt.Println("超时")
return
}
}
}
}()
ch <- 1
close(ch)
time.Sleep(time.Second)
fmt.Println("main结束")
}
解答完毕!
网友评论