Go — no es solo un lenguaje de moda, sino una herramienta para el desarrollo rápido
\n\nGo (o Golang) se ha convertido en los últimos años de un lenguaje exótico a un estándar de la industria para backend, microservicios y aplicaciones en la nube. Sus creadores (Rob Pike, Ken Thompson) hicieron deliberadamente el lenguaje simple, pero el diablo, como siempre, está en los detalles. Muchos principiantes se estancan en la etapa de «escribí Hello World, ¿y ahora qué?».
\n\nEn este artículo he recopilado consejos de desarrolladores senior que te ayudarán no solo a aprender la sintaxis de Go, sino a acelerar el aprendizaje de Go y comenzar a escribir código listo para producción. Analizaremos casos reales, errores típicos y daremos elementos de acción concretos. ¡Allá vamos!
\n\n1. Olvídate de la «POO de Java» — piensa en composición
\n\nEl error más común de los principiantes es intentar aplicar la POO clásica (herencia, polimorfismo de clases) a Go. En Go no hay clases ni herencia. En su lugar — estructuras e interfaces.
\n\nLos desarrolladores senior aconsejan: aprende Go a través de la composición. Incrusta una estructura dentro de otra, usa interfaces para la abstracción.
\n\nEjemplo: cómo NO hacerlo
\n// Mal: intento de hacer "herencia" mediante incrustación con sobrescritura de métodos\ntype Animal struct {\n Name string\n}\nfunc (a Animal) Speak() string {\n return "I am an animal"\n}\n\ntype Dog struct {\n Animal\n}\nfunc (d Dog) Speak() string {\n return "Woof!"\n}\n\n\nEjemplo: cómo hacerlo bien (composición + interfaces)
\n// Bien: usamos interfaz y composición\ntype Speaker interface {\n Speak() string\n}\n\ntype Dog struct {\n Name string\n}\n\nfunc (d Dog) Speak() string {\n return "Woof! I'm " + d.Name\n}\n\nfunc MakeSound(s Speaker) {\n fmt.Println(s.Speak())\n}\n\nfunc main() {\n dog := Dog{Name: "Rex"}\n MakeSound(dog) // Funciona con cualquier Speaker\n}\n\n\nConsejo de senior: «Empieza con interface{} — es la interfaz vacía. Entiende cómo Go verifica los tipos mediante type assertion. Esto te ahorrará semanas.»
2. Las gorutinas no son solo «go func()»
\n\nLas gorutinas son la característica estrella de Go. Pero los principiantes a menudo escriben:
\ngo myFunc()\n// ... y se olvidan de la sincronización\n\n\nEsto provoca condiciones de carrera (data races). Los desarrolladores senior aconsejan siempre usar sync.WaitGroup o canales para la sincronización.
Patrón correcto: Worker Pool
\npackage main\n\nimport (\n "fmt"\n "sync"\n "time"\n)\n\nfunc worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) {\n defer wg.Done()\n for j := range jobs {\n fmt.Printf("Worker %d processing job %d\\n", id, j)\n time.Sleep(time.Second) // simulación de trabajo\n results <- j * 2\n }\n}\n\nfunc main() {\n const numJobs = 5\n jobs := make(chan int, numJobs)\n results := make(chan int, numJobs)\n var wg sync.WaitGroup\n\n // Iniciamos 3 workers\n for w := 1; w <= 3; w++ {\n wg.Add(1)\n go worker(w, jobs, results, &wg)\n }\n\n // Enviamos tareas\n for j := 1; j <= numJobs; j++ {\n jobs <- j\n }\n close(jobs)\n\n // Esperamos a que todos los workers terminen\n wg.Wait()\n close(results)\n\n // Recogemos los resultados\n for r := range results {\n fmt.Println("Result:", r)\n }\n}\n\n\n¿Por qué esto acelera el aprendizaje de Go? Aprendes inmediatamente a trabajar con gorutinas de forma segura, sin fugas ni pánicos.
\n\n3. Los errores son valores (errors are values)
\n\nEn Go no hay excepciones (try-catch). Los errores son simplemente valores que deben manejarse. Los desarrolladores senior lo inculcan desde las primeras revisiones de código.
\n\nError típico de principiante:
\nresult, _ := doSomething() // Ignoramos el error\n\n\nCómo debe hacerse:
\nresult, err := doSomething()\nif err != nil {\n // Registramos, devolvemos, entramos en pánico (pero n