Tutorial de Migração em Go

1. Visão geral do Go Migrate

Go Migrate é uma ferramenta para gerenciar a migração de banco de dados escrita na linguagem Go. Pode ser utilizada como uma interface de linha de comando (CLI) ou importada como uma biblioteca para projetos em Go. Go Migrate pode ler arquivos de migração de diferentes fontes e aplicá-los ao banco de dados na ordem correta. Ele suporta vários drivers de banco de dados e fontes de migração.

2. Versões

Go Migrate suporta várias versões, incluindo:

  • Master: A versão mais recente, incluindo novos recursos e correções de bugs
  • v4: Versão estável, adequada para ambientes de produção
  • v3: Não é mais suportada e não deve ser utilizada

3. Instalação

Para utilizar o Go Migrate, é necessário instalar o pacote Go. Execute o seguinte comando para instalar:

go get -u -d github.com/golang-migrate/migrate/v4
cd $GOPATH/src/github.com/golang-migrate/migrate/v4

3. Utilizando o Go Migrate

Go Migrate pode ser utilizado através da CLI ou como uma biblioteca no projeto Go.

3.0. URLs de Conexão com Banco de Dados

Ao utilizar a CLI ou código Go, as URLs de conexão do banco de dados precisam ser configuradas para a conexão com o banco de dados.

Formato da URL:

dbdriver://username:password@host:port/dbname?param1=true&param2=false

Esta URL é uma URL de conexão com o banco de dados utilizada para se conectar ao banco de dados e especificar os parâmetros de conexão. Aqui está uma explicação para cada parte:

  1. dbdriver://: Este é o identificador de protocolo para o driver de banco de dados utilizado para especificar qual driver de banco de dados usar, por exemplo, mysql.
  2. username:password: Este é o nome de usuário e a senha utilizados para autenticação. Normalmente, o nome de usuário e a senha são separados por dois pontos (:).
  3. @: Este símbolo é utilizado para separar o nome de usuário e senha do nome do host e porta.
  4. host:port: Este é o nome do host e o número da porta do servidor de banco de dados. O nome do host é o endereço IP ou nome de domínio do servidor de banco de dados, e o número da porta é a porta na qual o servidor de banco de dados está ouvindo.
  5. /dbname: Este é o nome do banco de dados ao qual se conectar.
  6. ?param1=true&param2=false: Esta parte são os parâmetros de consulta utilizados para especificar parâmetros de conexão adicionais. Neste exemplo, existem dois parâmetros.

Esses parâmetros de consulta podem ser definidos de acordo com os requisitos específicos do driver de banco de dados e do servidor de banco de dados para configurar atributos ou comportamentos específicos da conexão.

Parâmetros de Conexão do Postgres

postgres://postgres:password@localhost:5432/example?sslmode=disable

Parâmetros de Conexão do SQLite

sqlite3://caminho/para/banco-de-dados?consulta

Parâmetros de Conexão do MongoDB

mongodb://user:password@host:port/dbname?query

3.1 Uso da CLI

3.1.1 Uso Básico

Para utilizar a CLI, execute o seguinte comando:

migrate -source file://caminho/para/migrações -database postgres://localhost:5432/banco-de-dados up 2

Este comando aplica as migrações da fonte especificada para o banco de dados fornecido. O número "2" indica a quantidade de migrações a aplicar.

3.1.2 Uso do Docker

Go Migrate também pode ser utilizado com Docker. Execute o seguinte comando:

docker run -v {{ diretório de migração }}:/migrações --network host migrate/migrate -path=/migrações/ -database postgres://localhost:5432/banco-de-dados up 2

Este comando executa o Go Migrate em um contêiner Docker e aplica as migrações da fonte especificada para o banco de dados fornecido.

3.2 Utilizando em seu Projeto Go

Para usar o Go Migrate em seu projeto Go, você precisa importar os pacotes e bibliotecas necessários. Aqui está um exemplo:

import (
    "github.com/golang-migrate/migrate/v4"
    _ "github.com/golang-migrate/migrate/v4/database/postgres"
    _ "github.com/golang-migrate/migrate/v4/source/github"
)

func main() {
    m, err := migrate.New(
        "github://mattes:personal-access-token@mattes/migrate_test",
        "postgres://localhost:5432/database?sslmode=enable")
    m.Steps(2)
}

Este código inicializa o Go Migrate com a origem e o banco de dados especificados e, em seguida, aplica 2 migrações usando o método Steps.

Se você deseja usar um cliente de banco de dados existente, consulte o exemplo a seguir:

import (
    "database/sql"
    _ "github.com/lib/pq"
    "github.com/golang-migrate/migrate/v4"
    "github.com/golang-migrate/migrate/v4/database/postgres"
    _ "github.com/golang-migrate/migrate/v4/source/file"
)

func main() {
    db, err := sql.Open("postgres", "postgres://localhost:5432/database?sslmode=enable")
    driver, err := postgres.WithInstance(db, &postgres.Config{})
    m, err := migrate.NewWithDatabaseInstance(
        "file:///migrations",
        "postgres", driver)
    m.Up()
}

Este código importa os pacotes necessários e inicializa o cliente de banco de dados com o pacote sql. Em seguida, cria uma nova instância do Go Migrate usando o método NewWithDatabaseInstance, especificando a origem e o driver do banco de dados. Por fim, aplica a migração usando o método Up.

4. Drivers de Banco de Dados Suportados

O Go Migrate suporta vários drivers de banco de dados, incluindo:

  • PostgreSQL
  • PGX v4
  • PGX v5
  • Redshift
  • Ql
  • Cassandra
  • SQLite
  • SQLite3
  • SQLCipher
  • MySQL/MariaDB
  • Neo4j
  • MongoDB
  • CrateDB
  • Shell
  • Google Cloud Spanner
  • CockroachDB
  • YugabyteDB
  • ClickHouse
  • Firebird
  • MS SQL Server

5. Origens de Migração Suportadas

O Go Migrate suporta várias origens de migração, incluindo:

  • Sistema de Arquivos: Lê migrações do sistema de arquivos local.
  • io/fs: Lê migrações usando o pacote io/fs do Go.
  • Go-Bindata: Lê migrações de dados binários incorporados usando o pacote jteeuwen/go-bindata.
  • pkger: Lê migrações de dados binários incorporados usando o pacote markbates/pkger.
  • GitHub: Lê migrações de um repositório remoto do GitHub.
  • GitHub Enterprise: Lê migrações de um repositório remoto do GitHub Enterprise.
  • Bitbucket: Lê migrações de um repositório remoto do Bitbucket.
  • Gitlab: Lê migrações de um repositório remoto do Gitlab.
  • AWS S3: Lê migrações do Amazon Web Services S3.
  • Google Cloud Storage: Lê migrações do Google Cloud Platform Storage.

Dependendo dos requisitos do seu projeto, você pode armazenar os arquivos de migração de banco de dados nas fontes de armazenamento de arquivo suportadas mencionadas acima.

6. Arquivos de Migração

Os arquivos de migração no Go Migrate possuem formatos específicos de nome e conteúdo.

6.1 Formato do Nome do Arquivo de Migração

Cada migração consiste em um arquivo de migração "up" e um arquivo de migração "down" correspondente. Os nomes dos arquivos de migração devem seguir o seguinte formato:

{versão}_{título}.up.{extensão}
{versão}_{título}.down.{extensão}

A versão é um número único que representa a ordem em que as migrações devem ser aplicadas. O título é uma descrição opcional da migração. A extensão depende do sistema de banco de dados usado (por exemplo, para variantes SQL, use .sql).

6.2 Formato do Conteúdo da Migração

O conteúdo dos arquivos de migração varia dependendo do sistema de banco de dados, geralmente envolve escrever SQL diretamente.

Por exemplo, os seguintes são dois arquivos de migração:

  • 000001_create_users_table.up.sql
  • 000001_create_users_table.down.sql

Arquivo de migração 000001_create_users_table.up.sql

CREATE TABLE IF NOT EXISTS users(
   user_id serial PRIMARY KEY,
   username VARCHAR (50) UNIQUE NOT NULL,
   password VARCHAR (50) NOT NULL,
   email VARCHAR (300) UNIQUE NOT NULL
);

Arquivo de migração 000001_create_users_table.down.sql, o arquivo de reversão é principalmente usado para desfazer as operações anteriores, geralmente para fins de reversão.

DROP TABLE IF EXISTS users;

6.3 Reversibilidade da Migração

Escrever migrações reversíveis é considerado uma prática recomendada. Isso significa que as migrações de subida e descida devem ser capazes de ser executadas em qualquer versão, efetivamente recriando e limpando o estado do banco de dados.

Para garantir a reversibilidade, cada migração deve ter um arquivo correspondente de "subida" e "descida". O arquivo de migração de "subida" contém as operações para aplicar a migração, enquanto o arquivo de migração de "descida" contém as operações para desfazer a migração.

7. Uso do MySQL

O Go Migrate oferece suporte para bancos de dados MySQL. Para se conectar a um banco de dados MySQL, a URL do banco de dados precisa estar no seguinte formato:

mysql://user:password@tcp(host:port)/dbname?query

A URL pode incluir parâmetros de consulta, como o nome da tabela de migração, parâmetros TLS, etc. Para obter uma lista completa dos parâmetros de consulta, consulte a documentação do Go Migrate MySQL.

7.1 Parâmetros de Consulta da URL

  • x-migrations-table: O nome da tabela de migração.
  • x-no-lock: Definido como true para ignorar as declarações GET_LOCK/RELEASE_LOCK. Útil para versões MySQL multi-master.
  • x-statement-timeout: Aborta qualquer declaração que exceda o número especificado de milissegundos.
  • dbname: O nome do banco de dados a ser conectado.
  • user: O usuário para fazer login.
  • password: A senha do usuário.
  • host: O host a ser conectado.
  • port: A porta a ser vinculada.
  • tls: Parâmetros de conexão de criptografia TLS/SSL.
  • x-tls-ca: A localização do arquivo do CA (Autoridade de Certificação).
  • x-tls-cert: A localização do arquivo de certificado do cliente.
  • x-tls-key: A localização do arquivo da chave privada.
  • x-tls-insecure-skip-verify: Se deve usar SSL.

7.2 Uso com Clientes Existentes

Se você pretende usar o Go Migrate com um cliente MySQL existente, certifique-se de usar o parâmetro multiStatements=true ao criar o cliente. Aqui está um exemplo:

package main

import (
    "database/sql"
    
    _ "github.com/go-sql-driver/mysql"
    "github.com/golang-migrate/migrate/v4"
    "github.com/golang-migrate/migrate/v4/database/mysql"
    _ "github.com/golang-migrate/migrate/v4/source/file"
)

func main() {
    db, _ := sql.Open("mysql", "user:password@tcp(host:port)/dbname?multiStatements=true")
    driver, _ := mysql.WithInstance(db, &mysql.Config{})
    m, _ := migrate.NewWithDatabaseInstance(
        "file:///migrations",
        "mysql", 
        driver,
    )
    
    m.Steps(2)
}

Este código importa os pacotes necessários, cria um cliente de banco de dados MySQL e inicializa o Go Migrate com a instância do banco de dados. Em seguida, aplica duas migrações usando o método Steps.