Para entender cómo trabaja Go, primero debemos diferenciar dónde vive el lenguaje y dónde vive tu código. GOROOT es la ruta donde está instalado el compilador y la biblioteca estándar; es la base de todo el ecosistema. Históricamente, usábamos GOPATH como un contenedor único para todos nuestros proyectos (un “workspace” gigante), pero esto causaba problemas de ergonomía y conflictos de versiones catastróficos: si el Proyecto A necesitaba la librería X versión 1 y el Proyecto B necesitaba la misma librería en versión 2, no podías trabajar en ambos de forma aislada.
Para solucionar esto, Go introdujo el modelo de módulos [disponible desde Go 1.11, obligatorio desde Go 1.16], que permite que cada proyecto sea independiente mediante un archivo go.mod. Gracias a esto, GOPATH ya no es el lugar donde guardas tu código, sino que ha quedado relegado a ser una carpeta de soporte donde se guarda el GOMODCACHE (el caché de todas las dependencias que descargas) y tus binarios compilados. Solo necesitas interactuar con estos conceptos cuando algo falla en tu entorno o cuando necesitas limpiar el caché de dependencias. Si intentas gestionar dependencias manualmente sin módulos o si confundes tu carpeta de trabajo con el GOPATH, Go simplemente no encontrará tus paquetes o, peor aún, usará versiones incorrectas que romperán tu compilación.
package main
import (
"fmt"
"os"
"runtime"
)
func main() {
// runtime.GOROOT() nos devuelve la ruta real donde reside el motor de Go
fmt.Printf("Ruta de instalación (GOROOT): %s\n", runtime.GOROOT())
// os.Getenv("GOPATH") nos muestra la ruta base de nuestro workspace actual
gopath := os.Getenv("GOPATH")
fmt.Printf("Ruta de trabajo base (GOPATH): %s\n", gopath)
// La variable GOMODCACHE indica dónde se guardan las librerías de terceros
// Normalmente es una subcarpeta de GOPATH (pkg/mod)
modCache := os.Getenv("GOMODCACHE")
if modCache == "" {
// Si GOMODCACHE no está definida, Go la calcula usando GOPATH
fmt.Println("GOMODCACHE no está definida explícitamente, se usará el caché en GOPATH.")
} else {
fmt.Printf("Ruta de caché de módulos (GOMODCACHE): %s\n", modCache)
}
}
En el código anterior, hemos usado el paquete runtime para consultar runtime.GOROOT(), que es la forma más fiable de saber qué instalación de Go está ejecutando el programa en este preciso instante. Usamos os.Getenv para leer variables de entorno del sistema: GOPATH nos dice dónde Go guarda sus archivos de sistema y GOMODCACHE nos revela la ubicación exacta de los archivos descargados de internet cuando haces un go get. Es importante notar que, aunque GOPATH sigue existiendo, para ti como desarrollador, tu código ya no “vive” dentro de él, sino en la carpeta que tú elijas, gracias a que el sistema de módulos gestiona las rutas de forma independiente.
El error frecuente
Antes de los módulos, la gente solía hacer esto:
# ¡ESTO ES UNA PRÁCTICA OBSOLETA! cd $GOPATH/src/mi-proyecto go get github.com/algun/paquete
Hoy, si intentas trabajar así, te encontrarás con conflictos de versiones constantes. El error moderno más común es crear un proyecto y olvidar ejecutar go mod init <nombre-del-modulo>. Sin este comando, Go no sabe que estás usando el modelo de módulos y tratará de buscar tus paquetes en el viejo y problemático GOPATH/src, lanzando errores de “package not found” aunque el código parezca estar bien.
N° 7