2009-11-13 12 views
8

Todos los ejemplos que he visto hasta ahora implican bloqueo para obtener el resultado (a través del operador <-chan).¿Cómo puedo saber si se hace una rutina, sin bloquear?

Mi enfoque actual consiste en pasar un puntero a una estructura:

type goresult struct { 
    result resultType; 
    finished bool; 
} 

cual el goroutine escribe sobre la terminación. Entonces es una simple cuestión de comprobar finished siempre que sea conveniente. ¿Tienes mejores alternativas?

Lo que realmente pretendo es un sistema de ranura de señal de estilo Qt. Tengo la corazonada de que la solución se verá casi trivial (chan s tienen lotes de potencial inexplorado), pero todavía no estoy lo suficientemente familiarizado con el lenguaje para resolverlo.

Respuesta

13

Usted puede utilizar el "coma, ok" patrón (ver su página en "effective go"):

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

esto ya no es válido. – rog

+1

tienes que escribir: seleccionar { caso foo: = <-ch: predeterminado: } – rog

4

Select statements le permite comprobar varios canales a la vez, teniendo una rama al azar (de aquellos en los que la comunicación está a la espera):

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

Para todo el enviar y recibir expresiones en el "seleccionar" instrucción, las expresiones de canal se evalúan, junto con cualquier expresión que aparezca en el lado derecho de las expresiones de envío , en orden de arriba a abajo. Si se produce cualquiera de las operaciones resultantes , se elige una y se evalúan las declaraciones correspondientes y . De lo contrario, si hay un caso predeterminado, se ejecuta ; si no, la instrucción bloquea hasta que se complete una de las comunicaciones .

+0

@Jurily: ¿Estás seguro de eso? Debería ser correcto, pero se vería mejor sin el espacio después de '<-'. – u0b34a0f6ae

+0

+1; siempre use gofmt cuando publique código Go. – rog

3

También puede echar un vistazo al buffer de canal para ver si contiene cualquier cosa mediante el uso de len :

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

Esto no tocará la memoria intermedia del canal, a diferencia de foo, gotValue := <- ch que elimina un valor cuando gotValue == true.

Cuestiones relacionadas