embed para Migraciones SQL y Datos de Inicialización
Go 1.16+ embed te permite enviar archivos de migración SQL y scripts de inicialización dentro del binario compilado.
Busca en todas las páginas de la documentación
Go 1.16+ embed te permite enviar archivos de migración SQL y scripts de inicialización dentro del binario compilado.
Los artefactos de despliegue permanecen autocontenidos: la misma imagen de contenedor que ejecuta la API puede aplicar versiones de esquema sin montar un directorio del host.
//go:embed adjunta archivos o directorios a variables de tipo embed.FS.
Las bibliotecas de migración aceptan adaptadores io/fs o http.FileSystem sobre el FS incrustado.
Los datos de inicialización para desarrollo y pruebas pueden enviarse en un árbol incrustado separado de las migraciones de producción.
Tarjeta de receta de referencia rápida - lista para copiar y pegar.
package migrations
import (
"embed"
"io/fs"
)
//go:embed sql/*.sql
var files embed.FS
func FS() fs.FS {
sub, _ := fs.Sub(files, "sql")
return sub
}import (
"github.com/golang-migrate/migrate/v4"
_ "github.com/golang-migrate/migrate/v4/database/postgres"
"github.com/golang-migrate/migrate/v4/source/iofs"
)
source, _ := iofs.New(migrations.FS(), ".")
m, _ := migrate.NewWithSourceInstance("iofs", source, dbURL)
_ = m.Up()Cuándo recurrir a esto:
package main
import (
"database/sql"
"embed"
"fmt"
"io/fs"
"github.com/pressly/goose/v3"
_ "github.com/mattn/go-sqlite3"
)
//go:embed migrations/*.sql
var migrationFiles embed.FS
func main() {
db, _ := sql.Open("sqlite3", ":memory:")
defer db.Close()
goose.SetBaseFS(migrationFiles)
goose.SetDialect("sqlite3")
if err := goose.Up(db, "migrations"); err != nil {
panic(err)
}
var n int
_ = db.QueryRow(`SELECT COUNT(*) FROM sqlite_master WHERE type='table'`).Scan(&n)
fmt.Println("tables:", n)
}migrations/00001_init.sql:
-- +goose Up
CREATE TABLE widgets (id INTEGER PRIMARY KEY, name TEXT);
-- +goose Down
DROP TABLE widgets;Lo que esto demuestra:
go:embed agrupa los archivos SQL junto al archivo fuente de Go.goose.SetBaseFS lee las migraciones desde la memoria en lugar del disco.iofs de golang-migrate.embed.FS es de solo lectura y seguro para compartir entre goroutines.fs.Sub reduce la raíz cuando el SQL vive en un subdirectorio.| Ruta | Propósito |
|---|---|
migrations/*.sql | Esquema de subida/bajada versionado |
seed/dev/*.sql | Fixtures locales (embed separado opcional) |
testdata/schema.sql | Arranque de pruebas de integración |
internal/migrations | Paquete que exporta FS() para main |
d, err := iofs.New(migrations.FS(), ".")
m, err := migrate.NewWithInstance("iofs", d, "postgres", dbURL)"iofs" se empareja con el nombre del controlador de base de datos en NewWithInstance.//go:embed seed/* separado importado solo desde main_dev.go.INSERT ... ON CONFLICT DO NOTHING o migración Go de goose con bucles.go:embed.fs.FS.go run desde la raíz del módulo.| Alternativa | Usar Cuando | No Usar Cuando |
|---|---|---|
| Volumen ConfigMap (K8s) | Ops quiere parchear SQL en caliente sin recompilar | Necesitas artefactos de lanzamiento inmutables |
| Checkout de Git en contenedor | Dockerfile simple COPY migrations | Imágenes Distroless sin shell |
| Servicio de migración remoto | Registro de esquema centralizado | Equipos pequeños quieren simplicidad incrustada |
go:generate para agrupar SQL | Pipeline de generación de código personalizado | Std embed es suficiente |
| Flyway en sidecar JVM | Estándar empresarial | Unidad de despliegue Go pura |
Sí - las pruebas importan el mismo paquete y llaman a goose.Up contra bases de datos efímeras.
Mantén los archivos de migración en el paquete bajo prueba.
Usa variables separadas y directivas //go:embed por directorio.
El prefijo all: incrusta archivos ocultos si es necesario.
Etiquetas de compilación en archivos (//go:build dev) o comandos/paquetes separados.
El main de producción importa solo el paquete de migración de producción.
//go:embed migrations incrusta el árbol; usa fs.Sub para establecer la raíz del directorio de goose.
Verifica los objetivos de la placa en la compilación; WASM y las compilaciones embebidas pueden tener límites de tamaño.
Prueba el tamaño de la migración en objetivos restringidos.
go test que ejecuta Up y afirma que las tablas existen.
Falla la compilación si el patrón está vacío.
Los archivos de migración Go se compilan en el binario de forma natural; SQL usa embed.FS.
Elige un estilo por repositorio para claridad en la revisión.
La CLI en el portátil aún puede usar -path ./migrations mientras que el binario de producción usa iofs - mantén los archivos idénticos en git.
Los mismos archivos down que el flujo de disco; embed solo cambia el transporte.
La disciplina de reversión sin cambios.
El límite práctico es el tamaño del binario y la memoria, no la sintaxis de Go.
Divide las migraciones de datos grandes en migraciones Go por lotes.
Versiones de Stack: Esta página fue escrita para Go 1.26.x (predeterminado Green Tea GC, go fix modernizadores - verifica el parche en la compilación), chi (última versión - verifica en la compilación), gin (última versión - verifica en la compilación), echo (última versión - verifica en la compilación), google.golang.org/grpc (última versión - verifica en la compilación), sigs.k8s.io/controller-runtime (última versión - verifica en la compilación), kubebuilder (última versión - verifica en la compilación), tinygo (última versión - verifica los objetivos de la placa en la compilación), wazero (última versión - verifica en la compilación), y golangci-lint (última versión - verifica el conjunto de linters en la compilación).
Revisado por Chris St. John·Última actualización: 18 jul 2026