Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

All the examples I've seen so far involve blocking to get the result (via the <-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 lots of unexplored potential), but I'm not yet familiar enough with the language to figure it out.

like image 530
György Andrasek Avatar asked Nov 13 '09 17:11

György Andrasek


3 Answers

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

foo     := <- ch; // This blocks.
foo, ok := <- ch; // This returns immediately.
like image 139
James Antill Avatar answered Nov 01 '22 08:11

James Antill


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 := <- workchan:
            go do_work(w)
        case <- 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.

like image 32
u0b34a0f6ae Avatar answered Nov 01 '22 06:11

u0b34a0f6ae


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

if len(channel) > 0 {
  // has data to receive
}

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

like image 23
William Casarin Avatar answered Nov 01 '22 07:11

William Casarin