Go viene con varias herramientas de análisis estático que detectan errores antes de que el código llegue a producción. gofmt formatea el código de forma uniforme, goimports gestiona los imports automáticamente, go vet detecta errores comunes y staticcheck va mucho más allá para encontrar bugs reales y código muerto.
gofmt: formato único, sin debates
gofmt formatea el código según las reglas oficiales de Go. No hay configuración: todos los proyectos Go tienen el mismo estilo:
# ver el resultado sin modificar el fichero gofmt main.go # modificar el fichero directamente gofmt -w main.go # formatear todo el proyecto gofmt -w . # ver el diff gofmt -d main.go
goimports: gestión automática de imports
goimports hace todo lo que hace gofmt y además añade los imports que faltan y elimina los que no se usan:
go install golang.org/x/tools/cmd/goimports@latest goimports -w main.go
go vet: errores comunes detectados en tiempo de análisis
go vet ./...
Ejemplos de lo que detecta:
// 1. formato incorrecto en Printf
fmt.Printf("%d", "cadena") // vet: arg "cadena" for verb %d not a number
// 2. mutex copiado por valor (rompe la sincronización)
type T struct{ mu sync.Mutex }
func f(t T) {} // vet: t.mu is a sync.Mutex and must not be copied
// 3. error en la condición de un bucle
for i := 0; i < 10; i-- { // vet: loop variable decrements, loop never terminates
}
// 4. printf sin argumentos cuando el formato los requiere
s := "algo"
fmt.Printf(s) // vet: non-constant format string in call to fmt.Printf
staticcheck: análisis más profundo
staticcheck es un linter externo que detecta bugs reales, código inalcanzable, APIs deprecadas y patrones ineficientes:
go install honnef.co/go/tools/cmd/staticcheck@latest staticcheck ./...
Ejemplos de lo que detecta:
// SA1006: Printf sin argumentos (debería ser Print)
fmt.Printf("holan") // usar fmt.Println en su lugar
// SA4006: variable asignada pero nunca usada
func f() {
x := calcular()
x = otroCalculo() // la primera asignación nunca se usó
return x
}
// S1039: llamada a Sprintf innecesaria
s := fmt.Sprintf("%s", nombre) // mejor: s := nombre
golangci-lint: orquestador de linters
golangci-lint ejecuta docenas de linters en paralelo y es el estándar en proyectos grandes:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest golangci-lint run ./...
Configúralo con un fichero .golangci.yml en la raíz del proyecto para elegir qué linters activar.
Pre-commit hook: automatizar la calidad
#!/bin/sh
# .git/hooks/pre-commit
set -e
echo "Ejecutando gofmt..."
if [ -n "$(gofmt -l .)" ]; then
echo "Hay ficheros sin formatear. Ejecuta: gofmt -w ."
exit 1
fi
echo "Ejecutando go vet..."
go vet ./...
echo "Ejecutando staticcheck..."
staticcheck ./...
echo "Todo correcto."
chmod +x .git/hooks/pre-commit
Este hook rechaza commits que no pasen los checks básicos, garantizando que el código en el repositorio siempre cumple los estándares de calidad del equipo.
