Lanzamiento de goroutines
La palabra clave go, el ciclo de vida de las goroutines y WaitGroups
Lanzamiento de goroutines es una lección gratuita de Go Academy en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Go Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Go Academy incluye 4 lecciones en total.
¿Qué es una goroutine?
Una goroutine es una función ligera que se ejecuta de forma concurrente y que gestiona el runtime de Go. Las goroutines son mucho más económicas que los hilos del sistema operativo: puede ejecutar miles de ellas:
- Inícielas con la palabra clave
go - Pila inicial de aproximadamente 2 KB (crece dinámicamente)
- Las planifica el runtime de Go, no el sistema operativo
- Se comunican mediante canales, no mediante memoria compartida
La palabra clave go
Ante cualquier llamada a una función con go para iniciarla como una goroutine:
package main
import ("fmt"; "time")
func greet(name string) {
fmt.Printf("Hello, %s!\n", name)
}
func main() {
go greet("Alice") // runs concurrently
go greet("Bob") // runs concurrently
time.Sleep(100 * time.Millisecond) // wait for goroutines
fmt.Println("done")
}Ciclo de vida de una goroutine
Una goroutine comienza cuando se ejecuta la instrucción go y termina cuando su función retorna. Si main retorna, se terminan todas las goroutines:
package main
import ("fmt"; "time")
func worker(id int) {
fmt.Printf("Worker %d starting\n", id)
time.Sleep(time.Duration(id) * 50 * time.Millisecond)
fmt.Printf("Worker %d done\n", id)
}
func main() {
for i := 1; i <= 3; i++ {
go worker(i)
}
time.Sleep(300 * time.Millisecond) // naive wait
}sync.WaitGroup para la coordinación
Use sync.WaitGroup en lugar de sleep para esperar a que terminen las goroutines:
package main
import ("fmt"; "sync")
func worker(id int, wg *sync.WaitGroup) {
defer wg.Done() // signal completion
fmt.Printf("Worker %d working\n", id)
}
func main() {
var wg sync.WaitGroup
for i := 1; i <= 5; i++ {
wg.Add(1) // register one goroutine
go worker(i, &wg)
}
wg.Wait() // block until all Done()
fmt.Println("all workers finished")
}Goroutines anónimas
Inicie directamente una función anónima como goroutine; resulta útil para tareas concurrentes insertadas en línea:
package main
import ("fmt"; "sync")
func main() {
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
i := i // capture loop variable
wg.Add(1)
go func() {
defer wg.Done()
fmt.Printf("goroutine %d\n", i)
}()
}
wg.Wait()
}Problema de captura de la variable del bucle
Si no captura la variable del bucle, todas las goroutines pueden ver el mismo valor (el valor final): es un error clásico de concurrencia en Go:
package main
import ("fmt"; "sync")
func main() {
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go func(n int) { // pass i as argument — safe
defer wg.Done()
fmt.Println(n) // prints 0, 1, 2 in some order
}(i)
}
wg.Wait()
}Goroutines frente a hilos
Por qué se prefieren las goroutines a los hilos del sistema operativo:
- Pila inicial de 2 KB frente a aproximadamente 1 MB en los hilos del sistema operativo
- La creación tarda microsegundos frente a milisegundos
- Go multiplexa las goroutines en los hilos del sistema operativo de GOMAXPROCS
- Los cambios de contexto de las goroutines son cooperativos: no interviene el kernel
- Go gestiona la planificación para que pueda centrarse en la lógica
GOMAXPROCS
runtime.GOMAXPROCS controla cuántos hilos del sistema operativo ejecutan goroutines en paralelo (de forma predeterminada, tantos como CPU haya):
package main
import ("fmt"; "runtime")
func main() {
// Default: number of available CPU cores
fmt.Println("CPUs:", runtime.NumCPU())
fmt.Println("GOMAXPROCS:", runtime.GOMAXPROCS(0)) // 0 = query without changing
// Set to 1 for debugging race conditions:
// runtime.GOMAXPROCS(1)
fmt.Println("Goroutines:", runtime.NumGoroutine())
}Fugas de goroutines
Una fuga de goroutines ocurre cuando se inicia una goroutine que nunca termina. Entre las causas habituales se encuentran una recepción bloqueada en un canal, un mutex bloqueado o la falta de cancelación:
package main
import ("fmt"; "time"; "runtime")
func leaky() {
ch := make(chan int) // nobody sends to ch
go func() {
v := <-ch // blocks forever — goroutine leaked!
fmt.Println(v)
}()
}
func main() {
leaky()
time.Sleep(10 * time.Millisecond)
fmt.Println("goroutines:", runtime.NumGoroutine()) // > 1
}Buenas prácticas para goroutines
Directrices para las goroutines:
- Sepa siempre cómo terminará una goroutine
- Use
WaitGroupo canales para sincronizar, nosleep - Pase las variables del bucle como argumentos de función, no mediante un cierre
- Cancele las goroutines con
context; no las deje ejecutándose - Use el detector de condiciones de carrera:
go run -race main.go
Comprobación rápida
¿Cuál es la forma correcta de evitar el problema de captura de la variable del bucle en las goroutines?
Recapitulación: iniciar goroutines
Resumen:
- Inicie con
go fn(): son ligeras y económicas - Use
sync.WaitGrouppara esperar:Add(1),defer Done(),Wait() - Capture las variables del bucle mediante un argumento o una redeclaración
- Sepa siempre cómo termina cada goroutine para evitar fugas
- Use la opción
-racepara detectar condiciones de carrera de datos
Preguntas frecuentes
¿La lección «Lanzamiento de goroutines» es gratis?
Sí — el texto completo de «Lanzamiento de goroutines» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Go Academy, actualiza a CoddyKit PRO. El curso de Go Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Lanzamiento de goroutines»?
La palabra clave go, el ciclo de vida de las goroutines y WaitGroups Practicas Go Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Go Academy?
No se requiere experiencia previa. Go Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.
¿Cuánto tiempo toma la lección «Lanzamiento de goroutines»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Go Academy?
Sí. Cada lección de Go Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Lanzamiento de goroutines
- Channels sin búfer
- Channels con búfer
- Dirección de channels y patrones de pipelines