TGViewer
Библиотека Go-разработчика | Golang Библиотека Go-разработчика | Golang @goproglib · 24.1K subscribers
Post #7160 3.59K
❤️ Миграции базы данных на Go

Миграции в проекте рано или поздно превращаются в хаос. Кто-то забыл накатить скрипт, у кого-то локально другая версия схемы, а в проде вообще непонятно что.

goose — это инструмент для миграций на Go, который работает и как CLI, и как библиотека.

Что умеет

goose поддерживает Postgres, MySQL, SQLite, ClickHouse, MSSQL, Spanner, YDB и ещё несколько баз. Миграции пишутся на SQL или на Go. Есть поддержка embed.FS, чтобы вшивать миграции прямо в бинарник.

Можно применять миграции не по порядку, подставлять переменные окружения в SQL-файлы и запускать отдельные миграции без версионирования.

Если бинарник получается слишком большим, можно собрать без лишних драйверов:
go build -tags='no_postgres no_mysql no_sqlite3 no_ydb' -o goose ./cmd/goose


Как работать

Создаём первую миграцию:
goose create add_users_table sql


Goose сгенерирует файл вида 20250511120000_add_users_table.sql. Внутри два блока:
-- +goose Up
CREATE TABLE users (
id int NOT NULL,
name text,
email text,
PRIMARY KEY(id)
);

-- +goose Down
DROP TABLE users;


Всё, что после -- +goose Up, выполняется при накатывании миграции. Всё после -- +goose Down — при откате.

Применяем все миграции:
goose postgres "user=postgres dbname=mydb sslmode=disable" up


Откатываем последнюю:
goose postgres "user=postgres dbname=mydb sslmode=disable" down


Смотрим статус:
goose postgres "user=postgres dbname=mydb sslmode=disable" status


Чтобы не передавать драйвер и строку подключения каждый раз, можно задать переменные окружения или положить их в .env файл:
GOOSE_DRIVER=postgres
GOOSE_DBSTRING=postgres://admin:admin@localhost:5432/mydb
GOOSE_MIGRATION_DIR=./migrations


Миграции на Go

Если SQL не хватает, миграции можно писать на Go:
package migrations

import (
"database/sql"
"github.com/pressly/goose/v3"
)

func init() {
goose.AddMigration(Up, Down)
}

func Up(tx *sql.Tx) error {
_, err := tx.Exec("UPDATE users SET username='admin' WHERE username='root';")
return err
}

func Down(tx *sql.Tx) error {
_, err := tx.Exec("UPDATE users SET username='root' WHERE username='admin';")
return err
}


Встраивание миграций в бинарник

С Go 1.16 можно вшить SQL-файлы миграций прямо в приложение через embed.FS:
package main

import (
"database/sql"
"embed"
"github.com/pressly/goose/v3"
)

//go:embed migrations/*.sql
var embedMigrations embed.FS

func main() {
var db *sql.DB
// настройка подключения к БД

goose.SetBaseFS(embedMigrations)

if err := goose.SetDialect("postgres"); err != nil {
panic(err)
}

if err := goose.Up(db, "migrations"); err != nil {
panic(err)
}
}


➡️ Репозиторий

📍 Навигация: Вакансии • Задачи • Собесы

🐸 Библиотека Go-разработчика

#GoToProduction
  • 👍 15
  • 🔥 8
  • ❤ 3
  • 👾 1
More from @goproglib
  1. Sep 30, 2026🧑‍💻 Эмулятор AWS-сервисов Kumo — это небольшой инструмент на Go для локальной имитации A…
  2. Sep 29, 2026👨‍💻 Библиотека для написания LSP-серверов Написать свой Language Server с нуля на Go сло…
  3. Sep 28, 2026🤔 Вопрос с собеседования по Go Что выведет программа? ❤️ — 1 true / 0 false 🔥 — 1 true /…
  4. Sep 28, 2026👩‍💻 Что на самом деле происходит внутри Go map? После Go 1.24 обычный map внутри работае…
  5. Sep 26, 2026🔥 В Go 1.27 появился portable SIMD До этого SIMD-оптимизации в Go требовали архитектурног…
  6. Sep 25, 2026🤡🤡 📍 Навигация: Вакансии • Задачи • Собесы 🐸 Библиотека Go-разработчика #GoGiggle
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →