如何关闭多个发件人的频道?

时间:2019-11-13 03:53:45

标签: go channels

在某些情况下,我需要扇出发送到同一频道的接收器:

func MessagesFromSQS(ctx context.Context, sqsClient sqsiface.SQSAPI) chan *sqs.Message {
    messages := make(chan *sqs.Message)

    go func() {
        defer close(messages)
        wg := sync.WaitGroup{}

        for i := 0; i < parallelSQSReaders; i++ {
            wg.Add(1)
            go func() {
                defer wg.Done()

                for {
                    select {
                    case <-ctx.Done():
                        return

                    default:
                        // ...

                        for _, message := range result.Messages {
                            messages <- message
                        }
                    }
                }
            }()
        }

        wg.Wait()
    }()

    return messages
}

对我来说这很有意义。但是,竞赛检测器抱怨说,不同的goroutines以及发送和关闭通道。我意识到负责发送的goroutine应该与关闭的goroutine相同,但是正确的方法是什么?

编辑/已解决:感谢您的回复。事实证明,我没有正确读取种族探测器堆栈跟踪。我以为我更改的代码引入了错误,而不是发现SQS模拟中的错误。一旦我正确同步了ReceiveMessage(),就可以了。

1 个答案:

答案 0 :(得分:2)

当您知道将不再有写操作时(即,当所有辅助程序都完成后),关闭通道。

所以:

wg.Wait()
close(messages)

P.S。通过将select与频道撰写内容结合起来,可以对上下文取消的轮询进行重组,例如

for _, message := range result.Messages {

    select {
        case messages <- message:
        case <-ctx.Done():
            return
    }

}