- En Go 1.26 se introduce un comando
go fix completamente reescrito que puede mejorar el código automáticamente aprovechando las funciones más recientes del lenguaje y de las bibliotecas
- Esta herramienta detecta patrones de código mediante decenas de analizadores (analyzers) y aplica distintos modernizadores (modernizers) como
minmax, rangeint y stringscut para convertir código repetitivo o anticuado a formas más modernas
- Para dar soporte a la nueva función
new(expr), se agregó el analizador newexpr, que puede simplificar automáticamente funciones auxiliares como newInt
go fix genera efectos de sinergia al ejecutarse varias veces: distintos analizadores pueden proponer mejoras consecutivas, e incluye fusión automática de conflictos y eliminación de imports innecesarios
- El equipo de Go planea ampliar esto en el futuro mediante un paradigma de análisis de autoservicio (Self-service), para que los desarrolladores puedan definir y distribuir modernizadores para sus propias API
Resumen del comando go fix
- En Go 1.26,
go fix fue reimplementado por completo para ofrecer conversión automática de bases de código al estilo más moderno de Go
- El comando
go fix ./... modifica todos los paquetes bajo el directorio actual
- La opción
-diff permite previsualizar los cambios
- La lista de analizadores registrados puede consultarse con
go tool fix help, e incluye varias reglas de transformación como any, forvar, mapsloop y minmax
- Para ejecutar solo un analizador específico se usa una bandera como
-any; para excluirlo se indica -any=false
- Considerando las diferencias de código por plataforma, puede ejecutarse varias veces para distintas combinaciones de
GOOS y GOARCH
Modernizers — herramientas de modernización de código
- Desde Go 1.18, la introducción de genéricos amplió las posibilidades de simplificar código
- Ejemplo: usar
maps.Keys para recopilar claves de un map, o strings.Cut para dividir cadenas
- Para resolver el problema de que las herramientas de generación de código basadas en LLM mantienen patrones antiguos, se destaca la necesidad de actualizar el código open source reflejando los modismos más recientes de Go
- Los modernizadores incluidos en
go fix y gopls mejoran la legibilidad del código y también su valor de aprendizaje
- Ejemplos de modernizadores:
- minmax: reemplaza sentencias
if por funciones min/max
- rangeint: convierte bucles
for de 3 cláusulas a range-over-int
- stringscut: simplifica código basado en
strings.Index usando strings.Cut
La función new(expr) en Go 1.26
- La función
new se amplió para aceptar un argumento de valor, permitiendo inicialización con formas como new("go1.26")
- El analizador
newexpr encuentra funciones auxiliares como newInt, las simplifica a return new(x) y reemplaza los puntos de llamada por new(expr)
- Solo se aplica cuando se cumple la versión mínima de Go requerida, por ejemplo una directiva
go 1.26
- Puede aplicarse a toda la base de código con el comando
$ go fix -newexpr ./...
- Después de usarlo, las funciones auxiliares innecesarias pueden identificarse con la herramienta
deadcode
Sinergia y manejo de conflictos
- Existe un efecto de sinergia donde una corrección crea oportunidades para otras
- Ejemplo: después de aplicar
minmax, pueden aparecer propuestas de transformación adicionales
- También es posible una optimización en cadena como
stringsbuilder → fmt.Fprintf
go fix usa un algoritmo de fusión 3-way merge para combinar automáticamente conflictos entre cambios
- Si hay conflicto sintáctico, omite esa corrección y muestra una advertencia
- Los conflictos semánticos, como eliminación de variables o imports sin uso, requieren ajuste manual
- Los imports innecesarios se eliminan automáticamente
Integración con el framework de análisis de Go
go vet y go fix se integraron para compartir un framework de análisis común
vet se enfoca en detectar errores, mientras que fix se centra en correcciones automáticas seguras
- Los analizadores pueden ejecutarse desde varios drivers como
unitchecker, multichecker, gopls, staticcheck y Tricorder
- Mediante el sistema de facts, es posible compartir información entre paquetes
- Ejemplo: inferir que
log.Printf es un wrapper de fmt.Printf
gopls ofrece diagnóstico en tiempo real y sugerencias de corrección automática
Mejoras en la infraestructura de análisis
- La expansión del paquete inspector mejora la eficiencia de exploración del AST, y el tipo
Cursor permite navegar arriba, abajo, izquierda y derecha
- El indexado de llamadas de función mediante typeindex mejora la velocidad de análisis hasta 1000 veces
- Mejoras adicionales:
- disponibilidad del grafo de dependencias de la biblioteca estándar
- soporte para consultas de versión de Go por archivo
- ampliación de primitivas de refactorización para permitir cambios seguros como comentar código
- Algunos modernizadores quedan excluidos por cambios sutiles de comportamiento (caso
append([]string{}, slice...) → slices.Clone(slice))
- A futuro se prevé desarrollar un motor de pattern matching, un arnés de pruebas automatizado y una biblioteca precisa de operadores de corrección
Paradigma Self-service
- Desde Go 1.26 se anticipa la introducción de un modelo de análisis de autoservicio
- Los desarrolladores podrán definir y distribuir modernizadores para sus propias API
- Podrá ejecutarse a nivel de proyecto sin un proceso centralizado de aprobación
- Como primer paso, se incluye en vista previa una función de inliner guiado por anotaciones (Annotation-driven inliner)
- Planes a futuro:
- ejecutar analizadores definidos por el usuario mediante carga dinámica (dentro de
go fix o gopls)
- generalizar checks basados en flujo de control, por ejemplo validar invariantes como “open seguido de close” o “lock seguido de unlock”
- El objetivo es mejorar la eficiencia de mantenimiento y acelerar la adopción de las funciones más recientes de Go
1 comentarios
Opiniones de Hacker News
A finales de 2024, cuando los asistentes de código con LLM se expandieron rápidamente, fue interesante ver que estas herramientas tendían a reproducir tal cual el estilo de código Go existente de sus datos de entrenamiento
Incluso si se les indicaba que usaran sintaxis moderna, a veces lo ignoraban o hasta negaban que existiera
Para que los modelos del futuro reflejen los modismos de Go 1.25 más recientes, todo el código open source tendría que actualizarse a ese estilo
magic_quotesPero una vez que a un LLM le entra información incorrecta, casi es imposible corregirla
Es difícil rastrear con qué fundamento llegó el modelo a una conclusión, y solo queda esperar que se corrija en la siguiente versión
Parece simple y pasa la revisión, pero en realidad le faltan manejo de errores y casos límite
Si después de revisarlo se vuelve a pasar al LLM, sale un código que parece corregido, pero por dentro aparecen data races o deadlocks
Es un problema que se repite en casi todos los modelos
Go mantiene muy bien la compatibilidad hacia atrás, así que compila, pero el estilo del código termina siendo muy distinto
En Python sí ocurren rupturas reales de compatibilidad por cambios en la API
Aun así, Go es excelente como lenguaje para generación de código gracias a la estabilidad del lenguaje y su librería estándar
Como advirtió Rob Pike, esta tecnología es una contaminación del ecosistema de software
Mucha gente quiere la porquería (slop) de la “comodidad”, pero justamente ahí está el problema
Una herramienta que transforme automáticamente el código fuente al estilo más reciente es realmente genial
El ejemplo clásico es OpenRewrite en Java, pero en otros lenguajes no se me ocurren muchas similares
Si, como en Go, esta capacidad viene integrada en el lenguaje, eso eleva muchísimo la madurez del lenguaje
Parece probable que los nuevos lenguajes tomen como referencia este enfoque integrado de Go
Los IDE de JetBrains pueden refactorizar millones de líneas de código de una sola vez o convertirlas automáticamente a sintaxis nueva
También tienen funciones como ConvertToPrimaryConstructor
Y Structural Search and Replace trabaja a nivel de sintaxis del lenguaje, no solo de texto simple
Los analizadores de Roslyn en .NET también ofrecen sugerencias de corrección de código dentro del IDE
Enlace al tutorial
Gracias a eso, el código ha quedado mucho más limpio
Puede cambiar
concatymapporconcatMap, o simplificar expresionesifinnecesariasLos servidores LSP se quedan cortos y ni siquiera soportan refactorizaciones básicas como quitar argumentos
Estoy pensando si sería posible combinando jscodeshift o Claude
Gracias a estas herramientas de corrección automática (
go fix), Go es de verdad un lenguaje sobresalienteTengo expectativas de que la nueva función
rangeinttambién se refleje automáticamente congo fixAplausos para el equipo de Go
La velocidad de compilación también es increíblemente rápida
fordirectamente con expresiones regulares, pero ahora esta herramienta lo resuelve de una forma mucho más eleganteNo se mencionó en el artículo, pero mi función favorita es la directiva
//go:fix inlineInserta en línea, en el llamador, una función de una sola línea
Permite que quien escribe la librería haga una migración automática y natural de una función vieja a una nueva
Incluso si cambia el semver, se puede hacer un upgrade automático con
go fixEn este podcast de Wes McKinney que vi recientemente,
decía que Go es ideal para agentes de codificación gracias a su ciclo rápido de compilar y ejecutar, su sistema de tipos fuerte y su seguridad en entornos multihilo
Después de escucharlo, me volvió a interesar Go
El consolidado ecosistema de herramientas y convenciones de Go ayuda mucho al desarrollo basado en agentes
Con
go run main.gopuedes levantar enseguida el entorno de desarrollo, y además soporta varios worktrees, configuración centralizada y hasta una base de datos con migraciones aplicadasEn housecat-inc/cheetah comparten herramientas de este tipo
Estoy pensando en agregar
go fixal ciclo rápido que ya incluyego generate,go build,go testygo vetAprendiendo Python me di cuenta de que hay demasiadas formas distintas e inconsistentes de hacer lo mismo
Hasta extrañé que fuera como C, donde hay básicamente una sola manera
Me pregunto si Go ya llegó a ese punto
Quiero saber si es un lenguaje en el que puedes seguir las mejores prácticas sin ayuda de un LLM
Me impresiona el esfuerzo por evitar complejidad y mantener la simplicidad
Se lo recomiendo a cualquiera que esté cansado del caos de Python
El concepto de self-service analyzer me parece realmente interesante
Da la impresión de que los equipos de librerías grandes o infraestructura lo van a aprovechar bastante
Con una herramienta así, dan ganas de pensar que hasta un lenguaje sin compatibilidad hacia atrás podría ser viable
En el mundo de TypeScript, biome cumple ese papel
Por ejemplo, recomienda
for...ofen vez deforEach, y si lo usas junto con ultracite el flujo de trabajo se vuelve mucho más fluidoEn el archivo
agents.mddejé escrito “ejecutar biome fix después de modificar”, y gracias a eso la calidad del código se mantiene automáticamenteLa experiencia es mucho más ligera y eficiente que con eslint