如何在不阻塞的情况下判断 goroutine 是否已完成?

huangapple go评论102阅读模式
英文:

How do I find out if a goroutine is done, without blocking?

问题

到目前为止,我看到的所有示例都涉及阻塞以获取结果(通过<-chan操作符)。

我目前的方法是传递一个指向结构体的指针:

type goresult struct {
    result resultType;
    finished bool;
}

goroutine 在完成后写入该结构体。然后,在方便的时候,只需检查finished即可。你有更好的替代方案吗?

我真正想要的是一个类似于Qt的信号槽系统。我有一种直觉,解决方案看起来几乎是微不足道的(chan有很多未被探索的潜力),但我还不熟悉这种语言,无法弄清楚。

英文:

All the examples I've seen so far involve blocking to get the result (via the &lt;-chan operator).

My current approach involves passing a pointer to a struct:

type goresult struct {
    result resultType;
    finished bool;
}

which the goroutine writes upon completion. Then it's a simple matter of checking finished whenever convenient. Do you have better alternatives?

What I'm really aiming for is a Qt-style signal-slot system. I have a hunch the solution will look almost trivial (chans have <i>lots</i> of unexplored potential), but I'm not yet familiar enough with the language to figure it out.

答案1

得分: 14

你可以使用“逗号,ok”模式(参见他们在“effective go”页面上的说明):

foo     := <- ch; // 这会阻塞。
foo, ok := <- ch; // 这会立即返回。
英文:

You can use the "comma, ok" pattern (see their page on "effective go"):

foo     := &lt;- ch; // This blocks.
foo, ok := &lt;- ch; // This returns immediately.

答案2

得分: 6

选择语句允许您一次检查多个通道,选择一个随机分支(其中有等待通信的分支):

func main() {
    for {
        select {
        case w := <-workchan:
            go do_work(w)
        case <-signalchan:
            return
        // 如果没有可用的通信,则在此处执行默认操作
        default:
            // 执行空闲工作
        }
    }
}

对于“select”语句中的所有发送和接收表达式,通道表达式以自上而下的顺序进行评估,以及出现在发送表达式右侧的任何表达式。如果任何结果操作可以继续进行,则选择其中一个,并评估相应的通信和语句。否则,如果有默认情况,则执行该情况;如果没有,默认情况下该语句将阻塞,直到其中一个通信可以完成。

英文:

Select statements allows you to check multiple channels at once, taking a random branch (of the ones where communication is waiting):

func main () {
    for {
    select {
        case w := &lt;- workchan:
            go do_work(w)
        case &lt;- signalchan:
            return
        // default works here if no communication is available
        default:
            // do idle work
    }
    }
}

> For all the send and receive
> expressions in the "select" statement,
> the channel expressions are evaluated,
> along with any expressions that appear
> on the right hand side of send
> expressions, in top-to-bottom order.
> If any of the resulting operations can
> proceed, one is chosen and the
> corresponding communication and
> statements are evaluated. Otherwise,
> if there is a default case, that
> executes; if not, the statement blocks
> until one of the communications can
> complete.

答案3

得分: 5

你还可以通过使用len来查看通道缓冲区是否包含任何内容:

if len(channel) > 0 {
  // 有数据可接收
}

这不会触及通道缓冲区,不像foo, gotValue := <- ch,当gotValue == true时会移除一个值。

英文:

You can also peek at the channel buffer to see if it contains anything by using len:

if len(channel) &gt; 0 {
  // has data to receive
}

This won't touch the channel buffer, unlike foo, gotValue := &lt;- ch which removes a value when gotValue == true.

huangapple
  • 本文由 发表于 2009年11月14日 01:24:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/1730719.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定