Go代码中BRANCH1在LINE2与LINE3间执行是否会触发panic?
问题分析:Go代码是否会在特定场景下触发panic
先看给出的Go代码:
func main() { rand.Seed(time.Now().Unix()) ctx, cancelFunc := context.WithCancel(context.Background()) anies := make(chan any) go doSomething(ctx, anies) intn := rand.Intn(2) if intn == 0 { //BRANCH1 cancelFunc() close(anies) } time.Sleep(time.Second) } func doSomething(ctx context.Context, anies chan any) { for { if ctx.Err() == nil { //LINE2 anies <- 1 //LINE3 } } }
当BRANCH1分支在LINE2与LINE3的执行间隙触发时,一定会发生panic,原因如下:
doSomething执行到LINE2时,判断ctx.Err() == nil成立,说明此时context还未被取消。- 就在LINE2判断完成、LINE3执行前的间隙,BRANCH1触发:先调用
cancelFunc()让context进入取消状态,接着调用close(anies)关闭通道。 - 之后
doSomething继续执行LINE3的anies <- 1,此时通道已经被关闭,而Go语言中往已关闭的通道发送数据会直接触发panic,错误信息为send on closed channel。
另外补充:即便context已经被取消,doSomething的循环不会停止,它只是在每次循环开头判断ctx.Err(),但如果已经通过判断才遇到通道关闭,依然会触发panic。
内容的提问来源于stack exchange,提问作者GumbertGumbert
相关产品推荐
相关产品推荐

