不能像我期望的那样使并发工作

时间:2016-05-10 15:12:40

标签: go

我试图理解为什么我的代码不起作用,所以我设法在一个更简单的例子中重新创建问题。

我希望这段代码输出字符串“broadcast”“,但它不会输出任何内容。

package main

import (
    "fmt"
    "time"
)

type hub struct {
    handle    chan []byte
    broadcast chan []byte
}

func (h *hub) init() {
    for {
        select {
        case m := <-h.handle:
            handler(m)
        case _ = <-h.broadcast:
            fmt.Println("broadcasted")
        }
    }
}

var socketHub = hub{
    handle:    make(chan []byte),
    broadcast: make(chan []byte),
}

func main() {

    go socketHub.init()

    m := []byte("this is the message")
    socketHub.handle <- m

    time.Sleep(time.Second * 2)
}

func handler(m []byte) {
    // Do some stuff.
    socketHub.broadcast <- m
}

为什么这不起作用?

1 个答案:

答案 0 :(得分:7)

您的broadcast频道无缓冲。这意味着:

  1. 您将消息发送到handle频道:主要goroutine阻止直到...
  2. 在goroutine中,select案例会收到消息......
  3. 并调用(在goroutine中)handler,将消息发送到broadcast频道,直到...
  4. 就是这样:你的孩子goroutine正在阻止,等待接收消息。同时,您的主要goroutine睡眠,然后到达main的末尾,退出并终止该程序。

    您可以通过多种方式“解决”它:

    • 使您的broadcast频道缓冲:这样,goroutine会立即发送消息,并在for循环中返回,然后选择它并按预期打印
    • send中或通过在循环中调用handler制作go handler(m)个(新)goroutine
    • 有两个不同的goroutines听取handlerbroadcast

    您选择哪一个取决于您尝试解决的确切问题:在这个小例子中,很难找到“最佳”问题。