当使用for循环时,为什么这个golang程序在操场上挂起?

时间:2017-06-11 08:04:45

标签: go

考虑这个playground

    messages := make(chan int, 1)
    done := make(chan bool)
    go func() {
        for {
        select {
            case msg := <- messages:
                fmt.Println("receiver one", msg)
            case signal := <-done :
                fmt.Println(signal)
                return
            default:
                fmt.Println("no message received")
        } 
        }
    }()
    go func() {
        for {
        select {
            case msg := <- messages:
                fmt.Println("receiver two", msg)
            case signal := <-done :
                fmt.Println(signal)
                return
            default:
                fmt.Println("no message received")
        } 
        }
    }()
    go func() {
       for i := 0; i < 2; i++ {
           messages<-i
       }
       done<-true
       done<-true
       done<-true
    }()

    <-done

我正在尝试模拟从一个线程到另外两个线程的通信,但看起来上面的代码在我的本地运行正常而不是在操场上。

有没有让这个程序有效的技巧?

2 个答案:

答案 0 :(得分:2)

您应该从default语句中删除select子句。

由于select语句在for循环内且default子句阻止它阻塞,因此循环必须经过很多循环才能收到任何消息。

看起来Playground会检测到它并停止程序。

答案 1 :(得分:1)

正如@ dev.bmax已提到的那样,您以错误的方式使用default。 使用default关键字检查这个小article

另外,尝试在程序开头添加runtime.GOMAXPROCS(4),运行几次并检查输出以查看它是如何工作的:

https://play.golang.org/p/TLDHNg6urB

以下是您的正确示例:

https://play.golang.org/p/bc0TGdmx1Y

请注意,在这种情况下,您应该使用不同的通道来停止其他和主要的goroutines。