为了账号安全,请及时绑定邮箱和手机立即绑定

如何在 golang 中向频道发送者发出信号退出?

如何在 golang 中向频道发送者发出信号退出?

Go
四季花海 2021-09-10 10:11:46
我在 Go 中使用通道来处理各种数据管道。代码如下所示:type Channels struct {    inputs chan string    errc   chan error    quit   chan struct{}}func (c *Channels) doSomethingWithInput() {    defer close(c.quit)    defer close(c.errc)    for input := range p.inputs {        _, err := doSomethingThatSometimesErrors(input)        if err != nil {            c.errc <- err            return        }    }    doOneFinalThingThatCannotError()    return}func (c *Channels) inputData(s string) {        // This function implementation is my question}func StartProcessing(c *Channels, data ...string) error {    go c.doSomethingWithInput()    go func() {        defer close(c.inputs)        for _, i := range data {            select {            case <-c.quit:                break            default:            }            inputData(i)            }    }()    // Block until the quit channel is closed.    <-c.quit    if err := <-c.errc; err != nil {        return err    }    return nil}这似乎是在通道处理器之间传达退出信号的合理方式,并且基于这篇关于 Go 并发模式的博客文章。我在使用这种模式时遇到的困难是inputData函数。将字符串添加到input通道需要等待doSomethingWithInput()读取通道,但也可能会出错。inputData需要尝试并提供inputs频道,但如果被告知退出则放弃。我能做的最好的是:func (c *Channels) inputData(s string) {    for {        select {        case <-c.quit:            return        case c.inputs <- s:            return        }    }}从本质上讲,“在您的选择之间摇摆不定,直到其中一个坚持下去”。需要明确的是,我不认为这是一个糟糕的设计。只是感觉……很浪费。就像我错过了一些聪明的东西。当频道使用者出错时,如何告诉频道发送者在 Go 中退出?
查看完整描述

1 回答

?
鸿蒙传说

TA贡献1865条经验 获得超7个赞

您的 inputData() 很好,这就是这样做的方法。

在您的用例中,您的频道消费者,即接收者,又名 doSomethingWithInput() 是应该控制“退出”频道的人。实际上,如果发生错误,只需从 doSomethingWithInput() 返回,这将依次关闭退出通道并使发送者退出(将触发case <-quit:)。这实际上是聪明的一点。

请注意当 doSomethingWithInput() 退出时未缓冲和关闭的错误通道。你不能事后阅读它来收集错误。你需要在你的主函数中关闭它并用一些容量(make(chan int, 10)例如)初始化它,或者为它创建一个消费者 goroutine。您可能还想尝试使用 select 语句读取它:如果没有错误,您的错误检查代码将永远阻塞。


查看完整回答
反对 回复 2021-09-10
  • 1 回答
  • 0 关注
  • 277 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信