gpt4 book ai didi

select - 为什么这个 select 在实际执行第一个 case 时总是运行 default case?

转载 作者:IT王子 更新时间:2023-10-29 01:18:19 24 4
gpt4 key购买 nike

我正在尝试更好地了解 golang channel 。读书时this article我正在研究非阻塞发送,并提出了以下代码:

package main
import (
"fmt"
"time"
)

func main() {
stuff := make(chan int)
go func(){
for i := 0; i < 5; i ++{
select {
case stuff <- i:
fmt.Printf("Sent %v\n", i)
default:
fmt.Printf("Default on %v\n", i)
}
}
println("Closing")
close(stuff)
}()
time.Sleep(time.Second)
fmt.Println(<-stuff)
fmt.Println(<-stuff)
fmt.Println(<-stuff)
fmt.Println(<-stuff)
fmt.Println(<-stuff)
}

这将打印:

Default on 0
Default on 1
Default on 2
Default on 3
Default on 4
Closing
0
0
0
0
0

虽然我知道只有 0 会被打印,但我真的不明白为什么第一次发送仍然触发选择的 default 分支?

在这种情况下,选择行为背后的逻辑是什么?

Example at the Go Playground

最佳答案

您永远不会向stuff 发送任何值,在您到达fmt.Println 语句中的任何接收操作之前执行所有默认情况。如果没有其他操作可以继续,则立即采用 default 情况,这意味着您的循环将尽快执行并返回。

您想阻止循环,因此不需要 default 大小写。您也不需要在末尾使用 close,因为您不依赖关闭的 channel 来解除对接收的阻塞或从 range 子句中中断。

stuff := make(chan int)
go func() {
for i := 0; i < 5; i++ {
select {
case stuff <- i:
fmt.Printf("Sent %v\n", i)
}
}
println("Closing")
}()
time.Sleep(time.Second)
fmt.Println(<-stuff)
fmt.Println(<-stuff)
fmt.Println(<-stuff)
fmt.Println(<-stuff)
fmt.Println(<-stuff)

https://play.golang.org/p/k2rmRDP38f

另请注意,最后的“Sent”和“Closing”行未打印出来,因为您没有其他同步等待 goroutine 完成,但这不会影响此示例的结果。

关于select - 为什么这个 select 在实际执行第一个 case 时总是运行 default case?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45446429/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com