Break out of select loop?

时光毁灭记忆、已成空白 提交于 2021-02-05 20:19:57

问题


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:


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:


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:

  • http://www.goinggo.net/2013/11/label-breaks-in-go.html
  • http://golang.org/doc/go_spec.html#Break_statements



回答3:


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:


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
            }
        }
    }
    }()


来源:https://stackoverflow.com/questions/25469682/break-out-of-select-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!