打破选择循环?

时间:2014-08-24 07:55:15

标签: select concurrency go goroutine

我正在尝试在循环中使用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错了吗?

5 个答案:

答案 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)
        }
    }
}