【问题标题】:Select on blocked call and channel选择阻塞的呼叫和频道
【发布时间】:2020-12-23 15:41:52
【问题描述】:

我很确定我以前看过一个关于此的问题,但现在找不到。

基本上我想select 在一个被阻止的呼叫以及一个频道上。

我知道我可以将被阻止的调用推送到 goroutine 中并通过通道等待结果,但是这感觉像是错误的解决方案。

有没有一种我想念的惯用方式来写这个?

最好是这样的:

select {
case a <- c:
  ...
case ans := connection.Read():
  ...
}

【问题讨论】:

  • 您的“建议”解决方案将等待被阻止的呼叫或频道,以先发生者为准。根据您的问题文本,您希望等待被阻止的呼叫和频道(等待两者完成)。你想要哪个?
  • @icza 是的对不起的意思或:)

标签: go concurrency channel


【解决方案1】:

如果你有一个频道和一个你想要select 的函数,使用 goroutine 和频道是惯用的解决方案。请注意,如果从通道接收到值,则不会影响函数,它将继续运行。您可以使用context.Context 表示不再需要它的结果并且它可能会提前终止。

如果你被允许重构,你可以“让”函数在同一个通道上发送,所以你只需要从一个通道接收。

另一个重构想法是让函数监视相同的通道并提前返回,因此您可以在没有select 的情况下进行一次调用。

请注意,如果您需要在很多地方执行此操作,您可以创建一个辅助函数来异步启动它:

func launch(f func()) <-chan struct{} {
    done := make(chan struct{})
    go func() {
        defer close(done)
        f()
    }()
    return done
}

示例函数:

func test() {
    time.Sleep(time.Second)
}

然后使用它:

select {
case a := <-c:
    fmt.Println("received from channel:", a)
case <-launch(test):
    fmt.Println("test() finished")

}

Go Playground 上试用。

【讨论】:

    猜你喜欢
    • 2011-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 2021-06-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多