go vet, gofmt y staticcheck: calidad de código Go desde el terminal

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.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP