前言
本文主要对 Go 语言 for-select 嵌套下 break,continue 和 return 的行为进行测试以及记录。
break
break 后退出当前的 select 并继续执行 for 以内 select 以后的其他代码;不会打断外层 for 循环。
如果想要退出外层 for 循环需要使用 label,示例代码如下:
package main import ( "fmt" "time" ) func main() { ch1 := make(chan struct{}) go func() { time.Sleep(time.Second * 3) ch1 <- struct{}{} }() LOOP: for { select { case <-ch1: fmt.Println("<-ch1") break LOOP default: time.Sleep(time.Second * 1) fmt.Println("default") } fmt.Println("for") } }
测试代码
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan struct{})
go func() {
time.Sleep(time.Second * 3)
ch <- struct{}{}
}()
for {
select {
case <-ch:
fmt.Println("<-ch")
break
default:
time.Sleep(time.Second * 1)
fmt.Println("default")
}
fmt.Println("for")
}
}
运行结果
default
for
default
for
default
for
<-ch
for
default
for
default
for
default
for
...
continue
continue 后继续执行其他 select 中可以运行的 case 以及 select 以后的其他代码,如果没有其他可以运行的 case 则执行 default;不会打断外层 for 循环。
测试代码
package main
import (
"fmt"
"time"
)
func main() {
ch1 := make(chan struct{})
ch2 := make(chan struct{})
go func() {
time.Sleep(time.Second * 3)
ch1 <- struct{}{}
}()
go func() {
time.Sleep(time.Second * 4)
ch2 <- struct{}{}
}()
for {
select {
case <-ch1:
fmt.Println("<-ch1")
time.Sleep(time.Second * 2)
continue
case <-ch2:
fmt.Println("<-ch2")
continue
default:
time.Sleep(time.Second * 1)
fmt.Println("default")
}
fmt.Println("for")
}
}
运行结果
for
default
for
default
for
<-ch1
<-ch2
default
for
default
for
default
for
default
for
...
return
return 后直接返回,没什么好说的。
测试代码
package main
import (
"fmt"
"time"
)
func main() {
ch1 := make(chan struct{})
go func() {
time.Sleep(time.Second * 3)
ch1 <- struct{}{}
}()
for {
select {
case <-ch1:
fmt.Println("<-ch1")
return
default:
time.Sleep(time.Second * 1)
fmt.Println("default")
}
fmt.Println("for")
}
}
运行结果
default
for
default
for
default
for
<-ch1
总结
与未测试前的想象有点不同,需要注意。