Saltar al contenido principal
eLearner.app
Módulo 7 · Lección 1 de 531/50 en el curso~12 min
Lecciones del módulo (1/5)

Gorutinas: paralelismo ligero

Una gorrutina es una unidad de ejecución concurrente administrada por Go tiempo de ejecución. Lanzas uno con la palabra clave go delante de una función llamar:

Go
go greet("Anna")         // chiamata a funzione esistente
go func() {              // funzione anonima
    fmt.Println("hi")
}()

La declaración go devuelve inmediatamente: la rutina comienza en paralelo y la persona que llama continúa.

Por qué son "ligeros"

  • Pila inicial ~2KB (crece dinámicamente, hasta cientos de MB si es necesario).
  • Multiplexado en una pequeña cantidad de subprocesos del sistema operativo mediante el tiempo de ejecución (GOMAXPROCS).
  • Miles/millones de gorutinas son rutinarias; con subprocesos del sistema operativo serían imposibles.

Conceptualmente es "disparar y olvidar simultáneamente", pero con todas las herramientas idiomáticas para coordinar (canales, sync.WaitGroup, CÓDIGOPH1).

principal no espera

Go
func main() {
    go func() { fmt.Println("ciao dalla goroutine") }()
    // main esce subito: niente garanzia che la goroutine completi
}

Cuando main regresa, el proceso termina: las gorutinas no obtienen para "terminar su trabajo", simplemente son asesinados junto con el proceso. Se requiere sincronización explícita.

Sincronización: una vista previa

Las tres herramientas que verás en las próximas lecciones:

Go
// 1) Channel: la goroutine "segnala" via canale
done := make(chan struct{})
go func() {
    work()
    done <- struct{}{}
}()
<-done   // attendi

// 2) sync.WaitGroup: N goroutine
var wg sync.WaitGroup
wg.Add(1)
go func() { defer wg.Done(); work() }()
wg.Wait()

// 3) context: cancellazione/timeout propagati

El error "clásico" de cierre en bucle

Hasta Go 1.21, este era un problema frecuente:

Go
for i := 0; i < 3; i++ {
    go func() { fmt.Println(i) }()  // stampa "3 3 3" su versioni vecchie
}

Desde Go 1.22 la variable for se crea recientemente en cada iteración, por lo que el error se soluciona de forma predeterminada. En bases de código más antiguas, podrás Todavía veo el patrón de corrección:

Go
for i := 0; i < 3; i++ {
    i := i           // shadow esplicito
    go func() { fmt.Println(i) }()
}
// oppure passa come argomento:
for i := 0; i < 3; i++ {
    go func(n int) { fmt.Println(n) }(i)
}

Goroutine! = Hilo del sistema operativo

AspectoGorrutinaHilo del sistema operativo
Pila inicial~2 KB1–8 MB (asignado al inicio)
Creaciónnanosegundosmicrosegundos
ProgramaciónIr en tiempo de ejecución (cooperativo)kernel (preventivo)
Conteo práctico100K+unos cuantos miles

Un único subproceso del sistema operativo puede albergar muchas rutinas. El tiempo de ejecución se mueve gorutinas a través de subprocesos cuando sea necesario.

Pruébalo

Ejercicio#go.m7.l1.e1
Intentos: 0Cargando...

Inicie la función de bienvenida como una rutina y espere 100 ms con el tiempo. Duerma antes de salir de principal.

Cargando editor...
Mostrar pista

`go` delante de una llamada de función lanza la rutina.

Solución disponible después de 3 intentos

Ejercicio#go.m7.l1.e2
Intentos: 0Cargando...

Inicie una función anónima como una rutina que imprima "hola".

Cargando editor...
Mostrar pista

Se llama a una función anónima con un `()` final: `go func(){...}()`.

Solución disponible después de 3 intentos

Cuestionario#go.m7.l1.e3
Listo

¿Qué sucede si `main` sale antes de que se complete una rutina?

Go
func main() {
  go work()
  // main ritorna immediatamente
}
Opciones de respuesta

Resumen

  • go f() lanza f() al mismo tiempo; regresa inmediatamente.
  • Goroutine = ~2 KB inicial, multiplexado en algunos subprocesos del sistema operativo.
  • main no espera: necesita sincronización (canal/Grupo de espera/contexto).
  • time.Sleep es sólo didáctico, nunca para sincronización en producción.
  • Desde Go 1.22, la variable for es "nueva" en cada iteración (no más errores "3 3 3").