Volver al blog

De Python a Go: lo que todo desarrollador debe saber

¿Llegas a Go desde Python? La sintaxis es lo fácil. Estos son los verdaderos cambios de mentalidad, de los errores como valores a las goroutines, con una guía rápida y un repaso honesto de lo que vas a extrañar.

De Python a Go: lo que todo desarrollador debe saber

Puedes leerte toda la sintaxis de Go en una tarde y, si ya escribes Python, casi todo te sonará. Esa familiaridad engaña. Las palabras clave nuevas se aprenden rápido. Lo difícil de pasar a Go es dejar un puñado de hábitos de Python que Go no admite. Go no tiene excepciones que capturar, ni clases de las que heredar, ni comprensiones de listas, ni un intérprete interactivo en el que probar cosas. A cambio tienes valores de error explícitos, structs con interfaces, goroutines y un compilador que protesta antes de que tu código llegue a ejecutarse. Este artículo repasa los cambios que deciden si tu primer mes con Go será un alivio o una pelea.

Resumen rápido

  • Los desarrolladores de Go están contentos con él. El 91 % de los encuestados dijo estar satisfecho con Go y unos dos tercios se declararon «muy satisfechos», el mejor resultado de la encuesta oficial de Google (Go Developer Survey 2025).
  • Ya usas la idea que hay detrás del mayor cambio de Go. El 88 % de los desarrolladores de Python dice usar anotaciones de tipo «siempre» o «a menudo», así que el tipado estático es un hábito que ya has empezado a practicar (Typed Python 2024 Survey, Meta).
  • Los equipos que migraron notaron mejoras reales. Cuando Khan Academy reescribió su backend de Python en Go, una página que tardaba unos 28 segundos en renderizarse pasó a tardar unos 4 segundos (Khan Academy Engineering). Al pasar a un servicio de comentarios escrito en Go, Reddit redujo a la mitad la latencia p99 de escritura (InfoQ).
  • Python sigue siendo más grande, y no pasa nada. Python lo usa el 54,8 % de los desarrolladores profesionales, frente al 17,4 % de Go, y domina el trabajo con datos e IA (Stack Overflow 2025). Go compite en un terreno más acotado: backends sensibles a la latencia, APIs y CLIs.

Índice

¿Deberías aprender Go si programas en Python?

Sí, sobre todo si tu trabajo se está moviendo hacia servicios backend, APIs, infraestructura o herramientas de línea de comandos. Los desarrolladores de Go declaran la mayor satisfacción de todos los lenguajes principales: en la encuesta oficial de Google, el 91 % está satisfecho y casi dos tercios, «muy satisfechos» (Go Developer Survey 2025). Esa satisfacción se debe más a que Go es predecible que a que sea ingenioso. La previsibilidad es lo que la mayoría de los desarrolladores de Python empieza a querer cuando una base de código supera unos pocos miles de líneas.

La transición es rápida porque gran parte de lo que ya sabes te sirve. Ya piensas en funciones, slices y maps. Ya divides el trabajo en paquetes y escribes tests. Tu forma de abordar los problemas sigue siendo la misma. Lo que cambia es lo estricto que es el lenguaje a la hora de hacerte cumplir tus decisiones. Go renuncia a parte de la flexibilidad de Python a cambio de garantías, y casi todo este artículo trata de dónde se nota eso.

Por qué los equipos pasan de Python a Go

Los equipos suelen migrar por el mismo motivo: un servicio en Python que fue rápido de escribir se volvió demasiado lento o demasiado caro de ejecutar. Cuando Khan Academy reescribió su servidor en Go, la lista de una clase de 1.000 estudiantes, que tardaba unos 28 segundos en cargar en Python, se renderizaba en unos 4 segundos, una mejora de casi 7 veces. Los avisos de contención del datastore bajaron de unos 100 por hora a prácticamente cero (Khan Academy Engineering).

A Reddit le pasó algo parecido. Tras trasladar el backend de su árbol de comentarios a un microservicio en Go en 2025, la latencia p99 de escritura quedó en la mitad que la del sistema heredado en Python, que en ocasiones había llegado a picos de 15 segundos (InfoQ).

Lovable, la plataforma para crear apps con IA, es el ejemplo reciente más llamativo. Reescribió todo su backend de Python a Go, 42.000 líneas de código. Las instancias de servidor bajaron de 200 a 10, los tiempos de despliegue pasaron de 15 minutos a 3 y las peticiones pasaron a ser, de media, un 12 % más rápidas (Lovable Engineering). La concurrencia motivó la reescritura. Una sola petición de chat en Lovable puede desencadenar más de 50 llamadas HTTP. Go maneja ese tipo de carga paralela de forma nativa, y el GIL de Python la complica.

En todos los casos, el runtime de Go, compilado, con tipado estático y recolector de basura, hace más trabajo por servidor, así que el mismo tráfico cuesta menos y se comporta de forma más estable bajo carga.

Tipado estático: ya tienes medio camino recorrido

De todo lo que trae Go, el tipado estático es lo que más suelen temer los desarrolladores de Python, y es a lo que antes se adaptan, porque la mayoría ya lo adoptó. En una encuesta de 2024, el 88 % de los desarrolladores de Python dijo usar anotaciones de tipo «siempre» o «a menudo», con mypy y Pydantic como herramientas más habituales (Typed Python 2024 Survey, Meta). Si anotas las firmas de tus funciones y ejecutas un comprobador de tipos en CI, ya has aceptado la premisa central de Go. Go hace obligatoria esa comprobación y la pone en el compilador en lugar de en una herramienta opcional.

La diferencia práctica está en cuándo te enteras de que te equivocaste. En Python, un error de tipos aparece en tiempo de ejecución, a menudo en producción y a veces horas después del despliegue. En Go, ese mismo error detiene la compilación. No puedes pasar una cadena donde se espera un int ni dejar una variable sin usar, así que un err que asignaste y nunca comprobaste no compila. Cuando estás empezando, parece que el compilador te regaña todo el rato. Si alguna vez has depurado un error NoneType has no attribute a las 2 de la madrugada, se parece más a una red de seguridad.

Así se ve en la práctica. La versión en Go no compila si Total llega a tener el tipo equivocado, mientras que una versión en Python simplemente confiaría en que quien la llama le pase un número:

example.gogo
type Order struct {
	ID    string
	Total int // cents, never a float, never a string
}

func discount(o Order, pct int) int {
	return o.Total - (o.Total * pct / 100)
}

La inferencia de tipos evita que esto se vuelva verboso. Con :=, Go deduce el tipo a partir del valor, así que escribes count := 0 en lugar de poner int por todas partes. Conservas la seguridad de las declaraciones y casi toda la brevedad de Python.

Los errores son valores, no excepciones

Este es el mayor ajuste, y te resultará raro durante más o menos una semana. Go no tiene try, ni except, ni excepciones en el sentido de Python. Las funciones que pueden fallar devuelven un error como último valor, y lo compruebas justo donde hiciste la llamada. No se lanza nada hacia arriba en la pila para capturarlo en algún lugar lejano. El error lo gestionas, lo ignoras o lo propagas en la misma línea donde ocurrió.

Vas a teclear este patrón miles de veces:

example.gogo
resp, err := http.Get(url)
if err != nil {
	return fmt.Errorf("fetch %s: %w", url, err)
}
defer resp.Body.Close()

Al principio, a muchos desarrolladores de Python no les gusta if err != nil. Tres líneas de gestión de errores después de cada llamada parecen ruido al lado de un único try que envuelve un bloque entero. Sin embargo, la repetición es deliberada. Puedes ver cada camino de fallo de la función leyendo de arriba abajo, sin saltos invisibles a un manejador lejano. El verbo %w envuelve el error original para que quien llama pueda seguir inspeccionándolo, y es la versión de Go de una cadena de excepciones.

Este hábito también te lo llevas de vuelta a Python. Cuando te acostumbras a gestionar los fallos en el punto de la llamada, un bloque except Exception genérico empieza a parecer lo que es: una forma de perder información sobre lo que falló.

Concurrencia: goroutines frente al GIL

La concurrencia es donde Go deja de ser «Python con tipos» y se convierte en una herramienta distinta. El Global Interpreter Lock de CPython permite que solo un hilo ejecute bytecode de Python a la vez, así que los hilos no pueden ejecutar trabajo intensivo en CPU en paralelo. Las compilaciones free-threaded, sin GIL, llegaron de forma experimental en Python 3.13 con la PEP 703, pero no son la opción por defecto y el ecosistema todavía se está poniendo al día (documentación de Python). Por ahora, escalar Python con carga intensiva de CPU suele implicar ejecutar varios procesos y pagar el coste de memoria y coordinación que eso conlleva.

Go se diseñó en torno a la concurrencia desde el principio. Una goroutine es una llamada a función con go delante, y el runtime reparte miles de ellas entre los núcleos de tu CPU sin ningún GIL de por medio. Las goroutines se comunican mediante channels en lugar de memoria compartida. Lanzar cien peticiones concurrentes requiere este código:

example.gogo
results := make(chan string)
for _, url := range urls {
	go func() {
		resp, err := http.Get(url)
		if err != nil {
			results <- "error: " + url
			return
		}
		defer resp.Body.Close()
		results <- url + " ok"
	}()
}
for range urls {
	fmt.Println(<-results)
}

Si has escrito asyncio, ya entiendes el objetivo. Go lo consigue sin partir tu código en dos mitades «coloreadas», async y síncrona. Cualquier función puede ejecutarse en una goroutine. No escribes await, no arrancas un event loop y no buscas versiones solo async de las bibliotecas. Esto explica en buena parte por qué los servicios en Go aguantan bien bajo carga: el modelo de concurrencia de Go viene integrado en el lenguaje en lugar de añadirse después.

Structs e interfaces en lugar de clases y herencia

Go no tiene clases ni herencia, algo que sorprende más de lo que debería. Modelas los datos con un struct y le das comportamiento asociándole métodos. Nada pasa self de forma implícita, no hay __init__ y no hay una clase base que extender. Donde Python usaría una jerarquía de clases, Go usa composición. Incrustas un struct dentro de otro para reutilizar sus campos y métodos, en lugar de heredar de un padre.

Las interfaces son donde Go se vuelve elegante, y no funcionan como esperarías. Un tipo satisface una interface solo por tener los métodos adecuados. No hay palabra clave implements ni paso de registro. Si tu struct tiene un método Read([]byte) (int, error), es un io.Reader. Es el duck typing que ya conoces de Python, comprobado en tiempo de compilación:

example.gogo
type Notifier interface {
	Notify(msg string) error
}

type SlackClient struct{ webhook string }

func (s SlackClient) Notify(msg string) error {
	// any type with this method is a Notifier, automatically
	return post(s.webhook, msg)
}

El cambio mental consiste en pasar de «qué es este objeto» a «qué puede hacer este objeto». Tus interfaces serán más pequeñas de lo que esperas, a menudo de un solo método, y las definirás junto al código que las usa en lugar de junto al tipo que las satisface. Esa inversión tarda unos días en sentirse natural. Después, suele ser una de las cosas que más extrañas cuando vuelves a Python.

Menos magia, más código explícito

Python premia el ingenio. Los decoradores, las metaclases, los métodos dunder, el monkey patching y el acceso dinámico a atributos te permiten moldear el lenguaje como quieras. Go deja fuera casi todo eso a propósito. No tiene decoradores, ni metaclases, ni sobrecarga de operadores, ni forma de añadir un método a un tipo que no es tuyo. Casi siempre puedes saber qué hace una línea sin conocer algo que ocurre en otra parte.

Esto resulta restrictivo el primer día y liberador al segundo mes. Leer una base de código de Go desconocida consiste casi solo en leer, porque nada oculto reescribe el comportamiento entre bastidores. La desventaja es que Go puede ser más verboso. A veces escribirás un bucle donde Python te daría una comprensión de una sola línea. La comunidad de Go lo considera un precio justo. Los diseñadores del lenguaje apostaron a que el código se lee muchas más veces de las que se escribe, así que optimizaron para quien lo lee.

Guía rápida de Python a Go

Casi todas las construcciones habituales de Python tienen un equivalente directo en Go. Ten esta tabla abierta durante tu primera semana. Los nombres cambian y la puntuación se vuelve más estricta, pero los conceptos se corresponden casi uno a uno.

PythonGoNota
x = 5x := 5:= infiere el tipo
def f(a, b):func f(a, b int) int {Los tipos se declaran, también el de retorno
list[]T (slice)Tiene tipo, pero crece como una lista con append
dictmap[K]VClaves y valores tienen tipo
for x in items:for _, x := range items {range da el índice y el valor
try / exceptif err != nil {Los errores se devuelven, no se lanzan
class Foo:type Foo struct {Más métodos e interfaces
NonenilPara punteros, slices, maps e interfaces
f"{name}"fmt.Sprintf("%s", name)No hay f-strings, usa el paquete fmt
pip installgo getLos módulos vienen integrados en el toolchain
# comment// commentLa misma idea, otro símbolo

Los mayores cambios visuales son las llaves y la desaparición de los dos puntos. Como Go tiene tipado estático, el compilador te frena en cuanto una traducción está mal. Aprovéchalo. Dejar que la compilación falle y leer el error es la forma más rápida de aprender las equivalencias.

Herramientas: un binario, un formateador, tests integrados

Las herramientas de Go son uno de los motivos más infravalorados por los que la gente se queda. No hay desajustes en requirements.txt, ni entorno virtual que activar, ni un formateador, un linter y un ejecutor de tests por separado que tengas que conectar entre sí. El comando go cubre todo eso y viene en una única instalación. Al compilar obtienes un único binario estático, sin intérprete ni dependencias que distribuir junto a él, así que desplegar muchas veces se reduce a copiar un archivo al servidor.

Lo primero que notarás:

  • go build genera un único binario. La máquina de destino no necesita Python instalado, no empaquetas un intérprete y los problemas de dependencias no aparecen al desplegar.
  • gofmt pone fin a las discusiones sobre formato. Go tiene un único estilo canónico y una herramienta que lo impone, así que en las revisiones de código nunca se debate sobre espacios en blanco. Piensa en black, pero integrado y usado por todo el mundo.
  • go test viene con el toolchain. Los tests viven junto a tu código en archivos _test.go y se ejecutan con un solo comando. No tienes que instalar ni configurar pytest.
  • go vet y el sistema de módulos vienen integrados. Las dependencias se versionan en go.mod y se descargan con go get, y las compilaciones son reproducibles sin herramientas de terceros.

Después de años gestionando entornos de Python, no tener que gestionar ninguno es un pequeño alivio cada día. Escribes código, ejecutas go build y despliegas el resultado.

Lo que vas a extrañar de Python

La rigidez de Go tiene costes reales, y conviene saber a qué renuncias. Lo que más vas a extrañar es el REPL. Go no tiene un intérprete interactivo para trastear con una biblioteca o probar un fragmento, así que explorar significa escribir un pequeño main y ejecutarlo. Extrañarás las comprensiones de listas y de diccionarios, porque Go te obliga a escribir el bucle cada vez. Y de vez en cuando extrañarás la flexibilidad de Python, esa forma de dejarte remodelar los datos sobre la marcha sin declarar antes un tipo.

La brecha de ecosistema importa más, porque afecta a tu carrera y no solo a tu comodidad. Python domina la ciencia de datos, el machine learning y la computación científica. Se ve en a qué dedican su tiempo los desarrolladores de Python: la exploración de datos, el desarrollo web y el ML encabezan la lista (JetBrains State of Python 2025). Si tu trabajo es entrenar modelos o pelearte con dataframes, Go no va a sustituir a Python ahí ni lo intenta. Tiene más sentido sumar Go que cambiar uno por otro. Quédate con Python para el trabajo con datos e IA y usa Go cuando necesites un servicio rápido y fiable, una CLI o herramientas de infraestructura. Eso coincide con lo que construyen los desarrolladores de Go: el 75 % crea servicios de API o RPC y el 62 % crea herramientas de línea de comandos (Go Developer Survey 2024 H2).

Cómo dar el salto

La forma más rápida de aprender Go si vienes de Python es dejar de leer sobre las diferencias y toparte con ellas en código real. Ya entiendes los conceptos. Lo que necesitas es repetición: suficientes ejercicios pequeños y corregidos como para que la sintaxis y el ritmo de la gestión de errores dejen de exigirte pensar en ellos. El paso de las excepciones a los errores como valores solo se asienta después de haber tecleado if err != nil unos cuantos cientos de veces en programas reales.

No caigas en ver tutoriales de forma pasiva. Ver a otra persona escribir Go te enseña muy poco sobre escribirlo tú, y es especialmente tentador cuando el lenguaje parece así de fácil. Escribe un poco de Go cada día, busca un feedback que te diga enseguida cuándo te equivocas y construye algo real en cuanto puedas escribir una función sin consultar nada. Una pequeña API JSON, una CLI que reformatea un archivo o un programa que llama a otro servicio y transforma la respuesta son proyectos cortos en Go, y usan los patrones en los que te apoyarás en el trabajo.

Preguntas frecuentes

¿Es Go más difícil de aprender que Python?

La sintaxis no lo es. Go tiene solo 25 palabras clave y un único estilo de formato obligatorio, así que hay menos que memorizar que en Python. Lo difícil es la disciplina: gestionar los errores como valores y declarar tipos exige más esfuerzo desde el principio. Los desarrolladores de Python que ya usan anotaciones de tipo, el 88 % de ellos, parten con una ventaja real (Typed Python 2024 Survey, Meta).

¿Por qué Go gestiona la concurrencia mejor que Python?

El Global Interpreter Lock de CPython solo deja que un hilo ejecute bytecode a la vez, así que el trabajo de CPU en paralelo necesita varios procesos (documentación de Python). Las goroutines de Go se ejecutan en todos los núcleos sin GIL, se comunican mediante channels y no necesitan un ecosistema async aparte. Ese modelo es una razón importante por la que los servicios en Go se mantienen más estables bajo carga.

¿Cuánto tarda un desarrollador de Python en aprender Go?

La sintaxis básica llega rápido, porque las funciones, los slices, los maps y los paquetes se trasladan casi igual desde Python. Escribir Go que un equipo aprobaría en una revisión de código lleva más tiempo. Lo que hace que Go sea idiomático es lo que Python nunca te enseñó: los errores como valores, las interfaces pequeñas, la composición en lugar de la herencia, las goroutines y los channels, y las convenciones de la biblioteca estándar. La mayoría de los desarrolladores necesita unos cuantos meses de dedicación construyendo proyectos reales antes de que todo encaje. Leer tutoriales no te llevará de «sé leer Go» a «escribo Go idiomático». La práctica estructurada sí, es decir, construir cosas y recibir feedback sobre ejercicios reales.

Para desarrollo backend, ¿sigo necesitando Python si aprendo Go?

No. Para el trabajo de backend, Go lo cubre todo por sí solo. La biblioteca estándar incluye servidores HTTP, JSON, drivers de SQL y concurrencia sin necesidad de un framework, así que puedes construir y desplegar servicios de producción íntegramente en Go. Compila a un único binario estático sin runtime que instalar, arranca rápido y maneja cargas con mucha concurrencia gracias a las goroutines, y por eso tanta infraestructura moderna funciona con él. Python sigue siendo la opción por defecto para ciencia de datos y machine learning, pero ese es otro trabajo. Para APIs, microservicios, CLIs y herramientas de infraestructura, con Go basta.

Empieza a escribir Go hoy

Tu experiencia con Python te ayuda aquí. Ya piensas con las formas adecuadas. Lo que queda es asimilar un pequeño conjunto de reglas nuevas, y eso se consigue escribiendo Go. La gestión de errores, las interfaces y las goroutines no son difíciles, pero cada una necesita práctica antes de que te resulte natural.

Para eso está hecho LevelUpGo. Cada lección es un ejercicio en el navegador que ejecuta tu código con el toolchain actual de Go y lo corrige al instante, así que escribes Go real desde el primer día.

Este es un camino si vienes de Python:

  • Empieza por los fundamentos. El curso Go Fundamentals te lleva de tu primer programa a las funciones, los tipos y los structs, y practica el patrón de gestión de errores desde el principio. Puedes empezar gratis, sin tarjeta de crédito.
  • Aprende el único modelo que de verdad es nuevo. El curso Go Concurrency Fundamentals enseña goroutines, channels y select. Python no tiene un equivalente directo, y es la parte que más rinde bajo carga.
  • Aprende a escribirlo al estilo Go. La ruta Clean Go Code cubre las convenciones idiomáticas, los nombres y la gestión de errores que hacen que tu Go se lea como Go y no como Python con llaves.

Empieza el curso gratis, escribe un poco de Go cada día y mantén tu racha.

Escribe Go como un ingeniero sénior

Lecciones interactivas en tu navegador. Las primeras son gratis.

Prueba una lección gratisO crea una cuenta gratuita