Introducción: Por qué Go parece simple, pero esconde trampas
Go (Golang) es un lenguaje compilado y de tipado estático creado en las profundidades de Google. A menudo se le elogia por su sintaxis simple, su soporte incorporado para la concurrencia y su alto rendimiento. Sin embargo, esta aparente simplicidad a menudo juega una mala pasada a los principiantes que vienen de lenguajes dinámicos (Python, JavaScript) o incluso de C++.
Muchos desarrolladores, al empezar a escribir en Go, cometen los mismos errores típicos. En este artículo, analizaremos las 5 principales fallas más comunes que enfrentan los desarrolladores principiantes de Go y mostraremos cómo solucionarlas con ejemplos de código claros.
1. Ignorar los errores devueltos (Manejo de Errores)
El problema
En Go no hay excepciones (try-catch). Un error es simplemente un valor que la función devuelve como último argumento. El error más común de un principiante es asignar el resultado a una variable, pero ignorar el error usando el guion bajo _.
// MAL: el error se tragaresult, _ := doSomething()fmt.Println(result)¿Por qué es malo?
El programa continuará ejecutándose con datos incorrectos, lo que puede provocar pánico, fugas de memoria o errores lógicos difíciles de detectar.
Cómo hacerlo bien
Siempre verifique el error. Use el patrón idiomático:
// BIEN: el error se manejaresult, err := doSomething()if err != nil { log.Printf("Error al ejecutar doSomething: %v", err) return // o panic, u otra lógica}fmt.Println(result)Consejo: Escriba su código de manera que if err != nil se convierta en su reflejo. No tema la devolución temprana (early return) — esto hace que el código sea más limpio.
2. Confusión entre nil y slices/mapas vacíos
El problema
En Go, nil no es un "objeto vacío". Es el valor cero para punteros, slices, mapas, canales e interfaces. Los principiantes a menudo intentan escribir datos en un mapa o slice nil, obteniendo un pánico.
// MAL: pánico al escribir en un map nilvar m map[string]intm["key"] = 42 // panic: assignment to entry in nil mapCómo hacerlo bien
Siempre inicialice los mapas y slices antes de usarlos:
// BIEN: inicialización con makem := make(map[string]int)m["key"] = 42
// O con un literalm2 := map[string]int{}m2["key"] = 42Con los slices, la situación es más sutil: se puede leer un slice nil (devolverá un slice vacío), pero no se puede escribir por índice. Use append:
var s []ints = append(s, 1) // OK, crea un nuevo slice// s[0] = 1 // panic: runtime error: index out of range [0] with length 03. Uso incorrecto de gorutinas y condición de carrera (Data Race)
El problema
Las gorutinas son hilos ligeros. Los principiantes a menudo lanzan gorutinas olvidando sincronizar el acceso a los datos compartidos. Esto lleva a una condición de carrera (data race) — un comportamiento indefinido del programa.
// MAL: condición de carreravar counter intfor i := 0; i < 1000; i++ { go func() { counter++ // ¡no seguro! }()}time.Sleep(time.Second)fmt.Println(counter) // resultado impredecibleCómo hacerlo bien
Use mutexes (sync.Mutex) o canales para la sincronización:
// BIEN: uso de mutexvar ( counter int mu sync.Mutex)for i := 0; i < 1000; i++ { go func() { mu.Lock() counter++ mu.Unlock() }()}// Esperamos a que termine (mejor usar sync.WaitGroup)time.Sleep(time.Second)fmt.Println(counter) // 1000Importante: Siempre verifique su código en busca de condiciones de carrera con la bandera -race: go run -race main.go.