GoLang: Por qué no usar el GOPATH

En las primeras versiones de Go configurarlo requería establecer algunas variables de entorno. Con el tiempo estos requisitos fueron eliminados pero muchos tutoriales online siguen mencionando estas variables causando confusión.

Recientemente se ha lanzado una nueva característica llamada Go Modules que finalmente hace innecesario el GOPATH. En este post, explicaré qué es el GOPATH, por qué se prefieren los Módulos Go y cómo configurar un proyecto para usar Módulos Go (que es sorprendentemente fácil).

El GOPATH es una variable de entorno que le dirá a Go dónde debe leer y descargar todos los archivos fuente que usará para compilar tu proyecto. Este concepto viene con algunas restricciones inusuales que no se ven en otros lenguajes de programación:

  • Requiere que escriba sus proyectos Go dentro de este directorio apuntado por la variable GOPATH (por defecto ~/go), incluso si sus otros proyectos residen en otros lugares;
  • La jerarquía de directorios dentro del directorio GOPATH debe reflejar la URL de su proyecto. Por ejemplo, si su URL es github.com/foo/bar necesita crear un directorio $GOPATH/src/github.com , luego, crear un nuevo directorio dentro de él: foo/ y dentro de él un nuevo directorio bar/ . Luego, dentro del directorio bar/ debes poner tu proyecto git real;
  • No hay ninguna manera incorporada para mantener un seguimiento de las versiones de los paquetes que estás utilizando.

El peor problema con esta configuración es que es completamente diferente de lo que estamos acostumbrados en la mayoría de otros lenguajes de programación. Además, como GOPATH es una variable de entorno, requiere que los usuarios sepan un poco sobre la configuración de su sistema operativo, lo que es propenso a errores, especialmente para los principiantes.

¿Por qué deberías usar Go Modules?

Go Modules no depende de ninguna de las dependencias mencionadas anteriormente para configurar variables de entorno específicas, ni de los requisitos para poner tu proyecto en un directorio específico como ocurre con GOPATH.

También es retrocompatible, seguro y fácil de usar:

  1. Requiere un solo comando para migrar un proyecto existente para usar Go Modules;
  2. Sólo afecta a tu entorno de desarrollo (al igual que GOPATH) por lo que no afectará a tu despliegue de producción de ninguna manera;
  3. Es retrocompatible con GOPATH, lo que significa que si actualizas un proyecto para usar Go Modules y tus compañeros de trabajo siguen prefiriendo usar GOPATH pueden hacerlo sin problemas.

Otra razón para aprender a usar Go Modules es que GOPATH probablemente dejará de ser ampliamente adoptado en el futuro, por lo que tendrá que aprenderlo tarde o temprano.

Hay, sin embargo, algunas advertencias:

Caveat 1: GoLang versión 1.11 o superior

Go Modules sólo funcionará con GoLang versión 1.11 o superior. En el momento de escribir este post, algunas distribuciones de Linux, incluida Ubuntu, todavía utilizaban GoLang 1.10.

Puedes probar la versión actual de tu paquete Go instalado con el siguiente comando:

go version

Debería salir algo como:

go version go1.11.2 linux/amd64

Si la versión que ves está por debajo de 1.11.x tendrás que desinstalarlo y seguir los pasos que se indican a continuación para instalar la versión Go necesaria. Además, ten en cuenta que las instrucciones de abajo fueron pensadas para funcionar en Ubuntu y distros derivadas, si estás usando alguna otra distro tendrás que adaptar los comandos para que te funcionen.

Primero, abre un terminal y ejecuta los siguientes comandos:

# If you have already installed the Go package remove it:
sudo apt-get remove --purge --auto-remove golang# Make sure your system is up-to-date:
sudo apt-get update
sudo apt-get -y upgrade# Download the Go 1.11 package and extract it:
wget https://dl.google.com/go/go1.11.linux-amd64.tar.gz
sudo tar -xvf go1.11.linux-amd64.tar.gz# Install it manually on your /usr/local directory:
sudo mv go /usr/local
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc# Then close your terminal, open a new one and test if Go is at the correct version:
which go # should output: /usr/local/go/bin/go
go version # should output: go version go1.11.x linux/amd64 or similar
  • Descarga el paquete Go 1.11 (o más reciente) y extráelo:
    wget https://dl.google.com/go/go1.11.linux-amd64.tar.gz
    sudo tar -xvf go1.11.linux-amd64.tar.gz
  • Instálalo manualmente en tu directorio /usr/local:
    sudo mv go /usr/local
    echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
  • Luego cierra tu terminal, abre una nueva y prueba si Go está en la versión correcta:
    which go, debería salir: /usr/local/go/bin/go
    go version, debería salir: go version go1.11.x linux/amd64 o similar
  • Si ya tienes instalado el paquete Go elimínalo:
    sudo apt-get remove --purge --auto-remove golang
  • Asegúrate de que tu sistema está actualizado:
    sudo apt-get update
    sudo apt-get -y upgrade
  • Descarga el paquete Go 1.11 y extráelo:
    wget https://dl.google.com/go/go1.11.linux-amd64.tar.gz
    sudo tar -xvf go1.11.linux-amd64.tar.gz
  • Instálalo manualmente en tu directorio /usr/local:
    sudo mv go /usr/local
    echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
  • Luego cierra tu terminal, abre una nueva y prueba si Go está en la versión correcta:
    which go, debería salir: /usr/local/go/bin/go
    go version, debería salir: go version go1.11.x linux/amd64 o similar

Caveat 2: Deshacer los cambios en GOPATH y GOROOT

Si has hecho cambios en los valores por defecto de tu GOPATH o GOROOT podría ser conveniente eliminar esos cambios. No son necesarios y mezclar las configuraciones de GOPATH con Go Modules es una forma de causar confusión. Más específicamente:

  1. El valor por defecto del GOPATH (cuando no está configurado) es ~/go , así que cuando menciono el directorio ~/go me refiero al directorio por defecto utilizado por Go. Si has hecho cambios en tu GOPATH, este directorio podría estar en otro lugar, así que, te sugiero que deshagas estos cambios para evitar confusiones.
  2. No deberías tener que cambiar la variable de entorno GOROOT ya que hemos instalado Go en el directorio por defecto: /usr/local. Sin embargo, si has cambiado esta variable de entorno te sugiero que la deshagas para evitar confusiones.

Caveat 3: No necesitas modificar el directorio ~/go

Como ya hemos mencionado ~/go es el directorio por defecto donde Go espera leer sus archivos cuando no se establece GOPATH. Sin embargo, esto sólo hace una diferencia si usted está planeando en la creación de sus proyectos utilizando GOPATH.

Si desea utilizar los módulos de Go no es necesario crear, editar o incluso leer el directorio ~/go. Si no existe todavía se creará automáticamente para ti, y si existe no deberías necesitar cambiar nada allí.

Así que puedes ignorar cualquier paso del tutorial que te pida hacer cambios en este directorio ya que probablemente se refieran a los requisitos de GOPATH.

Además, si tienes un proyecto Go actualmente dentro de este directorio y quieres que funcione con Go Modules deberías moverlo fuera ya que las versiones más antiguas de Go deshabilitarían el go mod dentro del GOPATH incluso si tuviera un archivo go.mod.

Usando Go Modules

Usar Go Modules consiste básicamente en usar el siguiente comando:

go mod init <your_projects_import_path>

Para crear un nuevo proyecto sólo tienes que crear un nuevo directorio (en cualquier lugar fuera de ~/go/) y luego inicializarlo como un módulo, es decir:

mkdir myProject/
cd myProject
go mod init github.com/myGithubName/myProject

El comando go mod init creará un nuevo archivo llamado go.mod en el directorio de tu proyecto. Este archivo contendrá la ruta de importación de su proyecto (normalmente la URL de su repo) y una lista con todos los paquetes que está utilizando actualmente en este proyecto.

No debería necesitar editar este archivo ya que es gestionado automáticamente por la mayoría de los comandos go como go run y go get . Por lo tanto, después de ejecutar estos 3 comandos has terminado de configurar este directorio como un módulo Go.

Para probarlo crea un nuevo archivo main.go dentro de este directorio con estas líneas de código:

package mainimport "fmt"func main() {
fmt.Println("Hello Go Modules")
}

Luego pruébalo usando el comando go run:

go run main.go 

Que debería dar como resultado Hello Go Modules como se espera.

Pero ya tengo un proyecto que usa GOPATH, ¿cómo migrar?

El proceso es similar:

  1. Mueve el directorio de tu proyecto a cualquier lugar fuera de ~/go/
  2. Inicialízalo como un módulo Go, por ejemplo.
mv ~/go/src/github.com/myGithubName/myProject ~/anywhere_else/
cd ~/anywhere_else/myProject
go mod init github.com/myGithubName/myProject

Luego puedes probar si todo funciona con go test ./... o go run main.go , ambos comandos descargarán automáticamente sus dependencias y actualizarán el archivo go.mod.

Eso es genial, ¿entonces debo crear módulos, submódulos y subsubmódulos? No.

Aunque es posible crear varios módulos en un mismo proyecto esto es casi siempre innecesario. Si quieres una subcarpeta para organizar tu código Go estás buscando paquetes, no módulos. Sólo debe ejecutar el comando go mod init una vez por proyecto, no más.

¿Qué debo hacer con los archivos `go.mod` y `go.sum`?

Al igual que con package.json y package-lock.json de NPM, el concepto de módulos Go también crea algunos archivos para mantener un registro de todas las versiones de sus dependencias, a saber, los archivos go.mod y go.sum.

No deberías necesitar editar ninguno de estos 2 archivos ya que son gestionados automáticamente por algunas herramientas go como go get y go test. También es una buena idea añadirlos a tus commits ya que son necesarios para realizar builds reproducibles de tu proyecto, es decir, compilar con todas las mismas versiones y paquetes que tienes localmente.

Conclusión

Ahora deberías estar listo para usar Go Modules en tus propios proyectos. Su uso no es obligatorio, pero si has leído hasta aquí probablemente habrás notado lo mucho más fácil e intuitivo que es Go Modules en comparación con GOPATH. También hay una característica que sólo Go Modules le ofrece: Construcciones reproducibles.

Si quieres conocer más detalles sobre Go Modules te sugiero que leas este post para una versión más corta o este otro para una más larga, ambos son muy concisos y fáciles de leer. También te recomiendo que hagas tu propia investigación, hay varios posts muy buenos sobre este tema en la web. Feliz codificación!

Deja una respuesta

Tu dirección de correo electrónico no será publicada.