🔎 Buscar

📦 Módulos y paquetes en Go

go mod init, go.mod y go.sum, dependencias y semver, GOPATH vs modules, estructura de proyecto profesional, exportación y la librería estándar clave.

Wiki / Apuntes📖 Contenido

Módulos y paquetes en Go

Un módulo es la unidad de distribución y versionado de Go: agrupa paquetes y declara sus dependencias. Desde Go 1.11 el sistema de modules es el estándar, reemplazando al antiguo GOPATH. Dominar módulos y paquetes es lo que separa un script suelto de un proyecto profesional.

¿Qué es un paquete?

Un paquete es una colección de archivos .go en el mismo directorio que comparten un package y un namespace. Es la unidad de compilación y reutilización.

  • package main genera un ejecutable (debe tener func main).
  • Cualquier otro nombre genera una biblioteca importable.
// archivo: greeting/greeting.go
package greeting

// Saludar devuelve un saludo. Exportado: empieza por mayúscula.
func Saludar(nombre string) string {
	return "Hola, " + nombre
}

Exportar: mayúsculas

En Go, la visibilidad se controla con la primera letra:

  • Mayúscula → exportado (visible fuera del paquete): Saludar, Config.
  • Minúscula → privado (solo dentro del paquete): saludar, config.
package greeting

var saludoPrivado = "Hola"   // no accesible desde fuera
var SaludoPublico = "Hola!"  // accesible desde fuera

💡 No existe public/private/protected. Si empieza por mayúscula, es público; si no, privado. Simple y contundente.

Inicializar un módulo

go mod init crea el go.mod con el path del módulo (normalmente tu repo: github.com/usuario/proyecto):

go mod init github.com/tuusuario/miapp

Esto genera:

module github.com/tuusuario/miapp

go 1.22

⚠️ Elige bien el path del módulo desde el principio: renombrarlo después obliga a actualizar todos los imports. Para proyectos locales sin publicar sirve cualquier nombre, pero la convención es el repo.

go.mod y go.sum

  • go.mod — declara el módulo, la versión de Go y las dependencias directas e indirectas.
  • go.sum — contiene los checksums (hashes) de cada dependencia para garantizar integridad y reproducibilidad. No lo edites a mano.
module github.com/tuusuario/miapp

go 1.22

require github.com/gorilla/mux v1.8.1

require (
	golang.org/x/sync v0.7.0 // indirect
)
  • // indirect — dependencia no importada directamente (dependencia de una dependencia).

Gestión de dependencias

Los comandos modernos de Go gestionan el go.mod automáticamente:

Comando Acción
go get paquete@version Añade o actualiza una dependencia
go get paquete@latest Última versión
go get -u ./... Actualiza todas
go add paquete Añade (nuevo, Go 1.22+)
go mod tidy Añade/elimina dependencias según lo importado
go mod download Descarga a la caché local
# añadir una dependencia concreta
go get github.com/gorilla/mux@v1.8.1

# limpiar: quita lo no usado, añade lo faltante
go mod tidy

💡 Corre go mod tidy antes de commitear. Mantiene go.mod/go.sum consistentes y elimina dependencias huérfanas.

Versiones semver

Go sigue Semantic Versioning (MAYOR.MENOR.PARCHE):

  • MAYOR — cambios incompatibles (v2, v3…).
  • MENOR — nuevas funciones retrocompatibles (v1.8).
  • PARCHE — correcciones (v1.8.1).

Los prefijos v son obligatorios: v1.8.1. Para versiones mayores a 1, el path del módulo suele incluir /v2.

import "github.com/usuario/lib/v2" // módulo en su v2

GOPATH vs modules

Antes de modules, todo vivía bajo $GOPATH/src y las dependencias se copiaban en $GOPATH/pkg/mod. Eso impedía versiones por proyecto.

Aspecto GOPATH Modules (moderno)
Ubicación del código fijo en $GOPATH/src cualquier carpeta
Versiones única global por proyecto en go.mod
Resolución go get global go get/go mod tidy local
Integridad no verificada go.sum
Estado obsoleto estándar desde Go 1.16

💡 go env GOPATH sigue existiendo para la caché de módulos, pero ya no defines tu código ahí. go env te muestra todas las variables.

Estructura de proyecto profesional

Go recomienda un layout estándar que separa lo ejecutable de lo interno:

miapp/
├── cmd/
│   ├── server/
│   │   └── main.go        # punto de entrada del ejecutable server
│   └── cli/
│       └── main.go        # otro ejecutable cli
├── internal/
│   └── services/
│       └── user.go        # código interno, no importable desde fuera del módulo
├── pkg/
│   └── utils/
│       └── strings.go     # código público reutilizable
├── go.mod
└── go.sum
  • cmd/ — un subdirectorio por ejecutable, cada uno con su main.go.
  • internal/ — código privado del proyecto: Go impide importarlo desde fuera del módulo. Regla de oro para APIs internas.
  • pkg/ — código público que otros proyectos pueden importar.

⚠️ internal/ no es un capricho: el compilador bloquea la importación de paquetes dentro de internal/ desde fuera del módulo. Úsalo para aislar implementación.

Importar paquetes

Imports por path del módulo + ruta relativa:

package main

import (
	"fmt"

	"github.com/tuusuario/miapp/internal/services"
	"github.com/tuusuario/miapp/pkg/utils"
)

func main() {
	fmt.Println(utils.Capitalizar("hola"))
	services.CrearUsuario()
}
  • Los imports se agrupan: estándar primero, luego terceros/propios (con gofmt/goimports).
  • Importar y no usar = error de compilación.

Paquetes estándar clave

La librería estándar de Go es enorme. Estos son los que usarás casi a diario:

Paquete Qué hace Ejemplo
fmt formato y salida fmt.Sprintf("%s", x)
strings manipular strings strings.Split, strings.Join
strconv convertir strings↔números strconv.Atoi
time fechas y tiempos time.Now(), time.Sleep
os sistema operativo, args, env os.Getenv, os.Args
io flujos de lectura/escritura io.Reader, io.Copy
net/http servidor y cliente HTTP http.Get
encoding/json serializar JSON json.Marshal
sort ordenar slices sort.Ints
errors crear y combinar errores errors.New, errors.Is
sync primitivas de concurrencia sync.WaitGroup
import (
	"encoding/json"
	"fmt"
	"strconv"
	"strings"
	"time"
)

func demo() {
	n, _ := strconv.Atoi("42")        // string -> int
	partes := strings.Split("a,b,c", ",") // ["a","b","c"]
	fecha := time.Now().Format("2006-01-02")

	datos, _ := json.Marshal(map[string]int{"a": 1})
	fmt.Println(n, partes, fecha, string(datos))
}

Herramientas: gofmt, go vet, go build

# formatea el código según el estilo oficial (obligatorio en la comunidad)
gofmt -w .

# analizador estático: detecta bugs y código sospechoso
go vet ./...

# compila sin generar binario (verifica que todo compila)
go build ./...

# ejecuta el paquete main
go run ./cmd/server

# compila e instala en GOBIN/GOPATH/bin
go install ./...
  • gofmt — normaliza sangría, espaciado e imports. Todos los proyectos Go pasan por él.
  • go vet — señala errores sutiles (printf incorrecto, copias de locks, etc.). Corre en CI.
  • go build vs go runbuild compila a binario; run compila y ejecuta en memoria.

💡 Instala el formateo automático en tu editor (on-save). go vet ./... debería correr en cada push o PR.

Cross-compile con GOOS y GOARCH

Go compila fácilmente para otras plataformas con variables de entorno. Compila sin dependencias nativas:

Variable Valores Significado
GOOS linux, darwin, windows sistema operativo objetivo
GOARCH amd64, arm64, 386 arquitectura objetivo
# binario de Linux x86-64 desde Windows
GOOS=linux GOARCH=amd64 go build ./...

# binario de Windows ARM64
GOOS=windows GOARCH=arm64 go build ./...

# compilar con nombre de salida
GOOS=linux GOARCH=amd64 go build -o server-linux ./cmd/server

⚠️ En PowerShell (Windows) no funcionan los prefijos VAR=valor de Unix. Usa $env:GOOS="linux"; $env:GOARCH="amd64"; go build ./... y luego Remove-Item Env:GOOS.

Cheatsheet

Necesitas… Usa…
Crear módulo go mod init <path>
Añadir dependencia go get <paquete>@<versión>
Limpiar dependencias go mod tidy
Código privado carpeta internal/
Ejecutables carpeta cmd/
Exportar mayúscula inicial
Formatear gofmt -w .
Analizar go vet ./...
Cross-compile GOOS / GOARCH

Para profundizar

Estudio · Recursos de todo el mundo (inglés, chino, japonés, español, francés, ruso…) curados y traducidos al español.