英文:
Break out of select loop?
问题
我正在尝试在循环中使用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
的方式有问题吗?
英文:
I'm trying to use a select
in a loop to receive either a message or a timeout signal. If the timeout signal is received, the loop should abort:
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)
}
}
}
However, it doesn't seem to be stopping:
$ 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
[...]
Why? Am I using time.After
wrong?
答案1
得分: 41
根据Go的规范,"break"语句会终止同一函数内最内层的"for"、"switch"或"select"语句的执行。
在你的示例中,你只是跳出了select语句。如果你将"break"替换为"return"语句,你会发现它可以正常工作。
英文:
The Go spec says:
> A "break" statement terminates execution of the innermost "for",
> "switch", or "select" statement within the same function.
In your example you're just breaking out of the select statement. If you replace break
with a return
statement you will see that it's working.
答案2
得分: 28
在这种情况下,"Go"的做法是使用标签和在标签上使用break,例如:
L:
for {
select {
case <-done:
break L
case num := <-numbers:
fmt.Println(num)
}
}
参考:
- http://www.goinggo.net/2013/11/label-breaks-in-go.html
- http://golang.org/doc/go_spec.html#Break_statements
英文:
The "Go" way for that kind of situations is to use labels and break on the label, for example:
L:
for {
select {
case <-done:
break L
case num := <- numbers:
fmt.Println(num)
}
}
Ref:
答案3
得分: 13
在你的示例代码中,正如Pat所说,使用return
是合适的,但是以后你可以使用标签(label):
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++
}
}()
readChannel:
for {
select {
case <-done:
break readChannel
case num := <-numbers:
fmt.Println(num)
}
}
// 其他逻辑...
fmt.Println("Howdy")
}
英文:
In your example code, a return
seems appropriate as Pat says, but for future reference you can use labels:
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")
}
答案4
得分: 9
我有以下解决方案,使用匿名函数。
func() {
for {
select {
case <-time.After(5 * time.Second):
if token := c.Connect(); token.Wait() && token.Error() != nil {
fmt.Println("连接错误:", token.Error())
} else {
fmt.Println("中断")
return
}
}
}
}()
请注意,这是一个使用匿名函数的示例代码。
英文:
I have the following solution, by using a anonymous function.
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
}
}
}
}()
答案5
得分: 5
使用一些控制变量来跳过循环怎么样?有时候使用break标签来理解可能有点困难或者不太容易理解。
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
// 这里不需要使用break
case num := <- numbers:
fmt.Println(num)
}
}
}
英文:
How about using some control variable to skip the loop? It's kind of hard or not so easy to understand with breaking label sometimes.
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)
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论