1Paquetes¶
Un paquete es una colección de archivos que contiene código fuente, definiciones de constantes, definiciones de tipos, etc. Todos los archivos de un paquete se encuentran en un mismo directorio.
Los paquetes organizan el código en forma lógica. Las variables, funciones y tipos de datos definidos dentro de un paquete son privados del mismo, es decir, no se pueden utilizar afuera, a menos que se exporten explícitamente.
Además de que todos los archivos estén en el mismo directorio, cada archivo que forma parte de un paquete debe declarar a qué paquete pertenece:
1package mipaquete
2Módulos¶
A su vez una colección de paquetes pueden conformar un módulo. Un módulo es la unidad fundamental de organización y distribución de código. Los módulos permiten gestionar dependencias, compartir código y versionarlo.
Un módulo se define en una carpeta que contiene un archivo go.mod. En este archivo se especifica el nombre del módulo, la versión de Go con la que se desarrolló y las dependencias de otros módulos.
Todos los paquetes (en general cada paquete en una subcarpeta) que están en la misma carpeta que contiene el archivo go.mod son parte del mismo módulo. En general un módulo corresponde a un proyecto.
2.1Gestión de módulos¶
Para crear un módulo se usa el comando go mod init dentro de la carpeta que contendrá el proyecto, seguido del nombre del módulo. Usualmente el nombre del módulo es el repositorio donde se aloja. Ejemplo:
go mod init github.com/untref-ayp2/miproyectoEste comando creará un nuevo archivo llamado go.mod con el siguiente contenido:
module github.com/untref-ayp2/miproyecto
go 1.24.1Todos los archivos que se encuentren dentro de la misma carpeta en la que se haya creado go.mod son los que serán considerados parte del módulo github.com/untref-ayp2/miproyecto
miproyecto
├── otropaquete
│ ├── estructuras.go
│ └── estructuras_test.go
├── unpaquete
│ ├── utils.go
│ └── utils_test.go
├── go.mod
├── go.sum
└── main.go2.2Importar paquetes¶
El objetivo final de organizar nuestro código en paquetes y módulos es que podamos reusarlos en otros proyectos. Cada vez que necesitemos usar una dependencia tanto interna a nuestro módulo como externa, debemos usar la instrucción import, lo que nos permite acceder a las estructuras, funciones y utilidades de los distintos módulos.
En Go existen distintos paquetes que podemos importar, dependiendo de su procedencia. Por ejemplo, Go provee una serie de paquetes que son parte de la biblioteca estándar del lenguaje, como pueden ser:
fmt- entrada y salida por pantalla y teclado
math- constantes y funciones matemáticas
time- funciones para medir y mostrar tiempos
errors- funciones para manipular errores
path- funciones para manipular carpetas y archivos
testing- soporte para test automáticos
strings- funciones para manipular cadenas de caracteres
Hasta ahora hemos utilizado mayormente este tipo de paquetes. También podemos utilizar referencias a paquetes dentro de nuestro mismo módulo.
1 2 3 4 5 6 7package main import "github.com/untref-ayp2/miproyecto/saludo" func main() { saludo.Saludar() }
La ruta completa del import (github.com/untref-ayp2/miproyecto/saludo) indica que debemos importar el paquete saludo, que es un subpaquete de nuestro módulo. El nombre del paquete (saludo) es la última parte de la ruta y es la referencia que usamos para acceder a sus miembros exportados.
Otros tipos de módulos que podemos importar son los módulos de otros programadores, por ejemplo, podríamos pensar en utilizar un supuesto módulo de algoritmos de ordenamiento de la cátedra. Entonces, imaginemos que existe el módulo llamado "untref.edu.ar/ayp2/busqueda". Podemos importarlo de la siguiente manera.
1 2 3 4 5 6 7 8 9 10 11 12package main import ( "fmt" "untref.edu.ar/ayp2/busqueda" ) func main() { lista := [10]int{2, 3, 9, 5, 1, 8, 4, -5, -4, 6} busqueda.Quicksort(lista) fmt.Println(lista) }
El resultado será:
[-5 -4 1 2 3 4 5 6 8 9]Hay varios puntos a notar:
Siempre se importan paquetes.
Cuando importamos un paquete, el texto luego de la última
/será el nombre de la referencia que podemos utilizar para acceder a los miembros del paquete, que además coincide con el nombre del paquete.Podemos renombrar la referencia que se crea al importar un paquete, ya sea por conveniencia como en el caso de que haya un conflicto de nombres entre paquetes de distintos módulos.
1import b "untref.edu.ar/ayp2/busqueda"Luego podremos utilizar la nueva referencia
ben lugar debusqueda.
3Dependencias¶
Cuando necesitamos utilizar un módulo de terceros, como podría ser un módulo que provee distintos métodos de ordenamiento, primero debemos encontrar el módulo, esto puede ser haciendo una búsqueda en el registro de go que podemos encontrar en https://pkg.go.dev/ o bien, buscando módulos en internet. Es posible instalar módulos directamente desde repositorios de Git.
Para instalar y agregar dicha dependencia en nuestro módulo, podemos utilizar la herramienta go get de la siguiente forma:
go get github.com/untref-ayp2/busquedasUna vez ejecutado este comando, el archivo go.mod, donde se encuentra la definición de nuestro módulo, se verá similar a:
module github.com/untref-ayp2/miproyecto
go 1.24.1
require github.com/untref-ayp2/busquedas v0.1.0De esta forma, si estamos trabajando con más personas en el mismo proyecto, o si alguien más quiere utilizar nuestro módulo como dependencia en su propio proyecto, será posible respetar los requerimientos que cada módulo en el proyecto necesita que se cumplan.
Si en lugar de instalar y agregar la dependencia con go get, tenemos una forma alternativa que es, primero usar la dependencia en nuestro código y luego ejecutar go mod tidy. Veamos un ejemplo.
Supongamos que creamos un módulo e importamos algunas cosas en nuestro archivo main.go.
3.1Ejemplo de creación de un módulo simple¶
Primero creamos una carpeta con el nombre mimodulo y nos posicionamos en ella.
mkdir mimodulo && cd mimoduloInicializamos el módulo.
go mod init github.com/untref-ayp2/mimodulogo: creating new go.mod: module github.com/untref-ayp2/mimodulocat go.modmodule github.com/untref-ayp2/mimodulo
go 1.24.1Usando cualquier método que les resulte conveniente creamos el archivo main.go con el siguiente código.
cat main.go1 2 3 4 5 6 7 8 9 10 11package main import ( "fmt" "github.com/fatih/color" ) func main() { msj := color.RedString("¡Texto en rojo!") fmt.Println(msj) }
Ejecutamos nuestro programa, pero vemos que hay un error.
go run main.gomain.go:5:2: no required module provides package github.com/fatih/color; to add it:
go get github.com/fatih/colorPodemos notar que los mensajes de error de Go muchas veces (no siempre) son muy descriptivos y hasta nos pueden sugerir la solución si prestamos especial atención a lo que nos dice.
Si bien en este ejemplo, queremos mostrar una forma alternativa de solucionar la falta de la dependencia, go get es otra forma de arreglar el problema que, intencionalmente, acabamos de crear.
Para ello usaremos go mod tidy, si consultamos la ayuda podemos aprender qué es lo que este comando realmente hace con nuestro módulo.
go help mod tidy[...]
Tidy makes sure go.mod matches the source code in the module.
It adds any missing modules necessary to build the current module's
packages and dependencies, and it removes unused modules that
don't provide any relevant packages. It also adds any missing entries
to go.sum and removes any unnecessary ones.
[...]Entonces, ya sabemos que go mod tidy se va a ocupar de agregar o corregir cualquier tipo de dependencia perdida en nuestro código.
go mod tidygo: finding module for package github.com/fatih/color
go: downloading github.com/fatih/color v1.18.0
go: found github.com/fatih/color in github.com/fatih/color v1.18.0
go: downloading golang.org/x/sys v0.25.0
go: downloading github.com/mattn/go-colorable v0.1.13Si ahora vemos cómo luce el archivo go.mod podemos comprobar que se agregó la directiva require donde se declaran las dependencias faltantes (pero adicionalmente go mod tidy también descargó esas dependencias en nuestro proyecto).
cat go.modmodule github.com/untref-ayp2/mimodulo
go 1.24.1
require github.com/fatih/color v1.18.0
require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
golang.org/x/sys v0.25.0 // indirect
)Si ahora ejecutamos nuevamente nuestro programa, todo debería funcionar como se espera.
go run main.go¡Texto en rojo!(el mensaje se imprime en color rojo en la terminal)
Los ejemplos de este capítulo están en 02-paquetes-y-modulos/ejemplos/ del repositorio taller-go.
4Ejercicios¶
Los ejercicios de este capítulo están en 02-paquetes-y-modulos/ejercicios/
del repositorio taller-go.