Golang:在多个goroutine中发送关闭通道错误

我有3个通道,可以一起获取数据。我的代码第一次运行完美,但是之后我又发送了另一个数据,出现错误:在关闭的通道上发送。在func FillNotCheckedDeliveryCh那一行中,我关闭了通道。如果我不关闭它,应用程序停止并且不继续。


func main() {

    receiveBulkIdsCh := make(chan int64, 100)

    NotCheckedDeliveryCh := make(chan CommonType.BasicRequestParameters, 100)

    ResultCh := make(chan CommonType.MessageStateResult, 100)


    var wg sync.WaitGroup

    wg.Add(4)


    /* Every BulkIds that receive from queue , save in  receiveBulkIdsChan channel*/

    go func() {

        defer wg.Done()

        PopQueue(receiveBulkIdsCh)

    }()

    go func() {

        defer wg.Done()

        for BulkId := range receiveBulkIdsCh {

            FillNotCheckedDeliveryCh(data, NotCheckedDeliveryCh)

        }

    }()

    go func() {

        defer wg.Done()

        for item := range NotCheckedDeliveryCh {

            for msgStatus := range DoFuncGetMessageState(item) {

                ResultCh <- msgStatus

            }

            close(ResultCh)

        }

    }()

    go func() {

        defer wg.Done()

        for Result := range ResultCh {

            ReadResultCh(Result)

        }

    }()

    wg.Wait()

}


func FillNotCheckedDeliveryCh(data IntegrateRowsFields, ch chan<- CommonType.BasicRequestParameters) {

    ch <- PackerForNotFinishedCh(data)

    defer close(ch)

}

可以帮助您解决什么问题?


慕后森
浏览 306回答 2
2回答

牛魔王的故事

当您在Go中使用频道时,发件人应始终关闭频道。因为这表明不再有数据将通过该通道发送。在您的代码中,接收器正在关闭它。只需将此处的通道保持打开状态,然后将其移除即可close(ch)。func FillNotCheckedDeliveryCh(data IntegrateRowsFields, ch chan<- CommonType.BasicRequestParameters) {&nbsp; &nbsp; ch <- PackerForNotFinishedCh(data)&nbsp; &nbsp; defer close(ch)}如果那部分有阻塞,您可以使用select:func FillNotCheckedDeliveryCh(data IntegrateRowsFields, ch chan<- CommonType.BasicRequestParameters) {&nbsp;&nbsp;&nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; case ch <- PackerForNotFinishedCh(data):&nbsp; &nbsp; &nbsp; default:&nbsp; &nbsp; }}

冉冉说

关闭接收器端的通道,然后尝试在同一通道上发送会给您带来错误。更好的做法是仅在所有值都在通道上发送之后,才在go例程之外关闭该通道。等待所有执行例程完成后关闭通道。wg.Wait() close(ch)当通道上没有其他值要发送时,请始终关闭通道。接收者可以通过向接收表达式分配第二个参数来测试通道是否已关闭:afterv,&nbsp;ok&nbsp;:=&nbsp;<-ch在您的情况下,您也可以通过使用ok在接收器端进行检查,以查看通道中是否有更多值或通道是否已关闭。频道不像文件。您通常不需要关闭它们。仅当必须告知接收者没有其他值来终止范围循环时,才需要关闭。去操场的例子,当不关闭通道并在其上移动时会产生错误。发送所有值后关闭通道的游乐场示例。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go