2009-11-13 9 views
8

Tutti gli esempi che ho visto finora coinvolgere il blocco per ottenere il risultato (tramite l'operatore <-chan).Come faccio a sapere se una goroutine è stata eseguita, senza bloccare?

mio attuale approccio consiste nel far passare un puntatore ad una struct:

type goresult struct { 
    result resultType; 
    finished bool; 
} 

cui il goroutine scrive al termine. Quindi è una semplice questione di controllare finished ogni volta che conveniente. Hai alternative migliori?

Quello che sto davvero puntando è un sistema di segnale slot in stile Qt. Ho la sensazione la soluzione avrà un aspetto quasi banale (chan s hanno sacco di potenziale inesplorato), ma io non sono ancora familiarità sufficiente con la lingua per capirlo.

risposta

13

È possibile utilizzare la "virgola, ok" modello (vedere la loro pagina su "effective go"):

foo  := <- ch; // This blocks. 
foo, ok := <- ch; // This returns immediately. 
+1

questo non è più valido. – rog

+1

dovete scrivere: selezionare { caso foo: = <-ch: default: } – rog

4

Select statements consente di controllare più canali in una sola volta, di prendere un ramo casuale (di quelli in cui la comunicazione è in attesa):

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 
    } 
    } 
} 

Per tutte le invio e ricezione espressioni nel "selezionare" dichiarazione, le espressioni del canale vengono valutate, insieme a eventuali espressioni che appaiono sul lato destro di inviare espressioni, in top-to-bottom ordine. Se una delle operazioni che possono procedere, si è scelto e la comunicazione corrispondenti e istruzioni vengono valutati. Altrimenti, se c'è un caso predefinito, quello viene eseguito; in caso contrario, l'istruzione blocca fino a quando una delle comunicazioni non può essere completata con .

+0

@Jurily: ne sei sicuro? Dovrebbe essere corretto, ma apparirebbe migliore senza lo spazio dopo '<-'. – u0b34a0f6ae

+0

+1; usa sempre gofmt quando pubblichi il codice Go. – rog

3

È inoltre possibile sbirciare il buffer del canale per vedere se contiene qualcosa utilizzando len :

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

Questo non toccherà il buffer del canale, a differenza foo, gotValue := <- ch che rimuove un valore quando gotValue == true.