golang中for select时,如果channel关闭会怎么样?
首先,如果对于一个已经关闭的channel来说,如果此时channel里还有值,则会正确读到channel里的值,且返回的第二个bool值为true;如果关闭前,channel里的值已经被读完,则最后返回的则是channel的零值;
那么针对该问题,我们通过代码来验证一下:
package main
import (
"fmt"
"time"
)
const timestamp = "2006-01-02 15:04:05"
func main() {
chan1 := make(chan int)
go func() {
time.Sleep(1 * time.Second)
chan1 <- 10
close(chan1)
}()
for {
select {
case x, ok := <-chan1:
fmt.Printf("%v,通道读取到:x=%v,ok=%v\n", time.Now().Format(timestamp), x, ok)
time.Sleep(500 * time.Millisecond)
default:
fmt.Printf("%v,通道未读取到,进入到default\n", time.Now().Format(timestamp))
time.Sleep(500 * time.Millisecond)
}
}
}
从结果中看出,我们可以继续读到channel里的值,但是读完之后,却依旧会继续执行读操作,这时候,可通过第二个参数bool值去解决该问题
for {
select {
case x, ok := <-chan1:
fmt.Printf("%v,通道读取到:x=%v,ok=%v\n", time.Now().Format(timestamp), x, ok)
time.Sleep(500 * time.Millisecond)
if !ok {
chan1 = nil
}
default:
fmt.Printf("%v,通道未读取到,进入到default\n", time.Now().Format(timestamp))
time.Sleep(500 * time.Millisecond)
}
}
从输出结果上看,该方法解决了该问题,因为将channel置为nil,在从channel去读数据的话,相当于操作一个为初始化的channel,会一直阻塞。
并且如果select里只有一个已经关闭的case的话,则会一直出现死循环的状态
for {
select {
case x, ok := <-chan1:
fmt.Printf("%v,通道读取到:x=%v,ok=%v\n", time.Now().Format(timestamp), x, ok)
time.Sleep(500 * time.Millisecond)
// if !ok {
// chan1 = nil
// }
// default:
// fmt.Printf("%v,通道未读取到,进入到default\n", time.Now().Format(timestamp))
// time.Sleep(500 * time.Millisecond)
}
}
那么针对上述场景,如果将其置为nil,又会怎么样呢?
for {
select {
case x, ok := <-chan1:
fmt.Printf("%v,通道读取到:x=%v,ok=%v\n", time.Now().Format(timestamp), x, ok)
time.Sleep(500 * time.Millisecond)
if !ok {
chan1 = nil
}
// default:
// fmt.Printf("%v,通道未读取到,进入到default\n", time.Now().Format(timestamp))
// time.Sleep(500 * time.Millisecond)
}
fmt.Println("the others information")
}
从输出结果上看,会panic,引发deadlocl问题,所以,select中最好放入一个default,来避免此类情况发生!
分类:
Go语言学习
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通