
Aprovecha al Máximo go.work y go.mod en Golang
Tabla de Contenido
Note
En este artículo, aprenderás a usar los módulos de Golang, qué son y cómo usarlos. Además, complementaremos el uso de múltiples módulos en un proyecto con la ayuda de go.work
.
¿Qué son los módulos de Golang?
Dentro del ecosistema de Golang para gestionar las dependencias de un proyecto, tenemos los módulos. Los módulos son una colección de paquetes de Golang que en conjunto forman una aplicación o librería. Entre los beneficios de los módulos de Golang se encuentran:
- Especificar las dependencias y sus versiones.
- Facilitar la descarga de las dependencias de un proyecto y compartirlas.
- Gestionar las importaciones de paquetes que componen el módulo.
- Actualizar y sincronizar las dependencias de un proyecto.
Los módulos en Golang se definen con el archivo go.mod
en la raíz del proyecto y este archivo tiene la siguiente estructura:
module <nombre-del-modulo>
go <go-version>
require (
<dependencia-1> <version>
<dependencia-2> <version>
...
)
replace (
<dependencia-1> => <ruta-local>
<dependencia-2> => <nueva-dependencia> <version>
...
)
En la anterior estructura se identifican cuatro partes principales:
- El nombre del módulo: Este puede tener cualquier nombre, sin embargo, es buena práctica definir un dominio en donde se alojará el módulo seguido de un path único.
- Definir la versión de Go: Especifica la versión de Golang que se usará en el proyecto.
- Las dependencias del proyecto: Se especifica el nombre de la dependencia y la versión que se usará. Esta sección no es obligatoria si el módulo no tiene dependencias.
- Directiva
replace
: Permite reemplazar las dependencias del módulo por otras dependencias o rutas locales, lo cual veremos en profundidad más adelante.
Note
Podemos hacer la analogía del archivo go.mod
con el archivo package.json
de Node.js o el archivo requirements.txt
de Python.
Junto con el archivo go.mod
encontramos el archivo go.sum
, el cual es un archivo autogenerado que no debes modificar manualmente. Este archivo contiene el listado de todos los paquetes de dependencias del módulo y sus respectivas versiones, sirviendo como referencia para verificar que las dependencias del módulo no hayan sido modificadas.
¿Cómo interactuar con los módulos de Golang?
Aunque podemos crear nuestros módulos manualmente creando el archivo go.mod
y definiendo las dependencias, Golang nos provee de una serie de comandos para interactuar con los módulos. Los más importantes son:
go mod init <module-name>
➔ Inicializa un módulo de Golang en el directorio actual, recibe como parámetro el nombre del módulo y creará el archivogo.mod
.go mod get <package-name>
➔ Descarga un paquete de dependencia del módulo y lo registra dentro del archivogo.mod
. Adicionalmente, puedes actualizar un paquete del módulo usando la bandera-u
, con el comandogo get -u <package-name>
.go mod tidy
➔ Sincroniza el estado actual del módulo en el archivogo.mod
, eliminando las dependencias que no se estén usando y agregando las que faltan pero que sí se están usando.go mod verify
➔ Verifica que las dependencias del módulo descargadas no hayan tenido modificaciones y estén sincronizadas con el archivogo.sum
.
Note
Un comando que no forma parte de go mod
pero que es muy útil es go list -m all
, el cual lista todas las dependencias del módulo y sus respectivas versiones.
¿Qué es Go Workspace?
Hasta este punto, hemos visto qué son y cómo se usan los módulos, pero hay una característica adicional asociada al contexto de los módulos. Cuando trabajamos en un módulo dentro de nuestro editor de código, Go tiene como contexto el directorio del módulo. El problema surge cuando queremos trabajar con varios módulos al mismo tiempo, ya que Go no sabría identificar en qué módulo estamos trabajando.
Este era un problema común en el desarrollo, ya que muchas veces se tenían módulos que dependían de otros módulos también desarrollados por el mismo equipo. En estos casos, si necesitabas probar cambios de un módulo en otro, tenías que actualizar la dependencia en cuestión y posteriormente actualizarla en el módulo que la usará, haciendo tedioso el proceso de desarrollo.
Normalmente, para solucionar esto, el desarrollador tenía que configurar manualmente las dependencias que estaba probando para que estas apuntaran a otro módulo o una ruta dentro de su máquina local. Esto se hace con la directiva replace
que mencionamos antes
. Este proceso se hacía manualmente y debías estar pendiente de actualizar y revertir los cambios antes de actualizar el paquete en el repositorio.
Dado todos estos inconvenientes, se agregó go.work
al ecosistema. La principal funcionalidad de los Go Workspaces es facilitar la gestión de los módulos en un mismo editor o contexto. Entre las ventajas de usar Go Work encontramos:
- Permite trabajar con múltiples módulos en un mismo editor.
- Puedes unificar el desarrollo de aplicaciones de Go que se componen de múltiples módulos en un mismo repositorio o ruta de trabajo.
- Mejora el flujo de desarrollo.
Su uso es muy similar a lo que ya vimos para go.mod
.
Note
go.work
se agregó en la versión 1.18 de Go, por lo que si estás usando una versión anterior a esta, no podrás usar go.work
.
¿Cómo usar go.work?
Lo primero que debemos hacer es crear el archivo go.work
en la raíz del proyecto. Este archivo tiene la siguiente estructura:
go <go-version>
use (
./<module-path>
)
Dentro de la estructura encontramos dos partes principales:
- La versión de Go: Especifica la versión de Golang que se usará en el proyecto.
- Directiva
use
: Especifica la ruta del módulo que se usará en el proyecto.
Aunque podemos crear el archivo manualmente, lo recomendable es hacerlo a través de los comandos de Go que están definidos para los Workspaces. Al igual que los módulos de Go, Go Work tiene una serie de comandos que nos permiten interactuar con los Workspaces. Los más importantes son:
go work init
➔ Inicializa un Workspace de Golang en el directorio actual, creando el archivogo.work
en la raíz del directorio.go work use <module-path>
➔ Agrega un módulo al Workspace. Este módulo debe estar ya creado dentro del folder<module-path>
, lo que significa que debe de tener definido el archivogo.mod
.go work sync
➔ Sincroniza los módulos del Workspace. Este comando descarga las dependencias de los módulos que están definidos dentro del Workspace.
Note
Si estás trabajando con un Workspace y un módulo que no está definido en el Workspace, Go no sabrá en qué módulo estás trabajando y te lanzará un error.
Con estos comandos, podrás interactuar con los módulos de Golang y el mismo Workspace será el encargado de resolver las dependencias sin necesidad de realizar configuraciones adicionales. Para explicar mejor qué significa esto, supongamos que tenemos el siguiente sistema de archivos:
proyecto/
├── go.work
├── modulo1/
└── modulo2/
Podríamos ejecutar comandos Go directamente dentro del módulo de la siguiente manera:
go test ./modulo1
go build ./modulo2
Todo desde la raíz del Workspace. Si no usáramos Workspace, tendríamos que abrir cada módulo en un nuevo editor o realizar las configuraciones pertinentes para que Go entienda qué módulo estamos trabajando.
Info
Este artículo se basa en mi experiencia como desarrollador y en la documentación que podemos encontrar en: