最近工作中有个地方要优化,涉及到较多的channel操作,发现gopl和effective-go中基本没有讲解select中break、continue和return的知识(可能觉得太简单?),导致他们的语义不太明确,本文通过代码示例来对起语义做出说明。
break、continue和return三个关键字在select中区别非常大,如果不彻底理解,写代码很容易翻车,导致写出不健壮或者危险的代码。
return
语义
和函数中的renturn语义一样
示例
package main
import (
"fmt"
"time"
)
func main() {
tick := time.Tick(time.Second)
for {
select {
case t := <-tick:
fmt.Println(t)
return
}
fmt.Println("for")
}
fmt.Println("main exit")
}
输出:
2019-07-11 13:04:22.874804802 +0800 CST m=+1.000547150
# main函数返回,即整个程序停止
break
语义
类似于switch中的break,break后的语句不会被执行到
示例
package main
import (
"fmt"
"time"
)
func main() {
tick := time.Tick(time.Second)
select {
case t := <-tick:
fmt.Println("t")
break
fmt.Println(t)
}
fmt.Println("main exit")
}
输出:
t
main exit
在for-select中,break只会影响到select,不会影响到for
package main
import (
"fmt"
"time"
)
func main() {
tick := time.Tick(time.Second)
for {
select {
case t := <-tick:
fmt.Println("t")
break
fmt.Println(t)
}
fmt.Println("for")
}
fmt.Println("main exit")
}
输出:
t
for
t
for
t
for
#...
continue
语义
单独在select中是不能使用continue,会编译错误,只能用在for-select中。continue的语义就类似for中的语义,select后的代码不会被执行到。
示例1
package main
import (
"fmt"
"time"
)
func main() {
tick := time.Tick(time.Second)
for {
select {
case t := <-tick:
fmt.Println("t")
continue
fmt.Println(t)
}
fmt.Println("for")
}
fmt.Println("main exit")
}
输出:
t
t
t
#...