我正在尝试在循环中使用select
来接收消息或超时信号。如果收到超时信号,则循环应该中止:
package main
import ("fmt"; "time")
func main() {
done := time.After(1*time.Millisecond)
numbers := make(chan int)
go func() {for n:=0;; {numbers <- n; n++}}()
for {
select {
case <-done:
break
case num := <- numbers:
fmt.Println(num)
}
}
}
然而,它似乎没有停止:
$ go run a.go
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[...]
3824
3825
[...]
为什么呢?我使用time.After
错了吗?
答案 0 :(得分:7)
Go spec says:
“break”语句终止执行最里面的“for”, “switch”或“select”语句在同一个函数中。
在你的例子中,你只是打破了select语句。如果您使用break
语句替换return
,您会看到它正在运行。
答案 1 :(得分:7)
在您的示例代码中,return
似乎与Pat说的相符,但为了将来参考,您可以使用标签:
package main
import (
"fmt"
"time"
)
func main() {
done := time.After(1 * time.Millisecond)
numbers := make(chan int)
// Send to channel
go func() {
for n := 0; ; {
numbers <- n
n++
}
}()
readChannel:
for {
select {
case <-done:
break readChannel
case num := <-numbers:
fmt.Println(num)
}
}
// Additional logic...
fmt.Println("Howdy")
}
答案 2 :(得分:3)
对于这种情况,“Go”方式是在标签上使用标签和中断,例如:
L:
for {
select {
case <-done:
break L
case num := <- numbers:
fmt.Println(num)
}
}
价:
答案 3 :(得分:0)
我有以下解决方案,使用匿名函数。
func() {
for {
select {
case <-time.After(5 * time.Second):
if token := c.Connect(); token.Wait() && token.Error() != nil {
fmt.Println("connect err:", token.Error())
} else {
fmt.Println("breaking")
return
}
}
}
}()
答案 4 :(得分:0)
如何使用一些控制变量来跳过循环?有时打破标签有点难或不太容易理解。
package main
import ("fmt"; "time")
func main() {
done := time.After(1*time.Millisecond)
numbers := make(chan int)
go func() {for n:=0;; {numbers <- n; n++}}()
completed := false
for !completed {
select {
case <-done:
completed = true
// no break needed here
case num := <- numbers:
fmt.Println(num)
}
}
}