for-select 的小坑
在某佬交流羣看到下面這樣一段代碼。
問,執行下面代碼會出現什麼現象?
func main() {
ac := make(chan int, 1)
ac <- 1
bc := make(chan int, 3)
bc <- 1
bc <- 2
for {
select {
case a := <-ac:
fmt.Println("from ac: ", a)
case b := <-bc:
fmt.Println("from bc: ", b)
default:
break
}
}
fmt.Println("do other thing")
fmt.Println("over")
}
go specification
A "break" statement terminates execution of the innermost "for", "switch", or "select" statement within the same function.
也就是說在 select 中,break 會中止其後面語句的執行,但是並不會打斷外層的 for 循環,所以上面的代碼會打印完 chan 中數據後一直陷入死循環,那麼解決方法有哪些呢?
continue
A "continue" statement begins the next iteration of the innermost "for" loop at its post statement. The "for" loop must be within the same function.
continue 語句會結束最內層的 for 循環。
for {
select {
case a := <-ac:
fmt.Println("from ac: ", a)
continue
case b := <-bc:
fmt.Println("from bc: ", b)
continue
default:
}
break
}
break label
If there is a label, it must be that of an enclosing "for", "switch", or "select" statement, and that is the one whose execution terminates.
break 可以打斷 for,select,switch 代碼標籤的運作,可以通過加個標籤來退出循環。
forSelectLoop:
for {
select {
case a := <-ac:
fmt.Println("from ac: ", a)
case b := <-bc:
fmt.Println("from bc: ", b)
default:
break forSelectLoop
}
}
goto
可以通過 goto 跳出循環。
for {
select {
case a := <-ac:
fmt.Println("from ac: ", a)
case b := <-bc:
fmt.Println("from bc: ", b)
default:
goto over
}
}
over:
fmt.Println("do other thing")
fmt.Println("over")
other
可以在 for 循環條件處做些標記。
var sign bool
for !sign {
select {
case a := <-ac:
fmt.Println("from ac: ", a)
case b := <-bc:
fmt.Println("from bc: ", b)
default:
sign = true
}
}
Reference
# https://go.dev/ref/spec#Break_statements
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/ALR8WzzUkEfCQ3sD28lr9w