So verwenden Sie Migrationen mit Golang
Einfache Beispielanwendung, die die Verwendung von golang-migrate zeigt
Warum sollten Sie Migrationen nutzen?
Viele Leute stellen diese Frage und ich habe versucht, diese Liste zu erstellen, um die wichtigsten Vorteile der Verwendung von Migrationen hervorzuheben:
Versionskontrolle: Eine der wichtigsten und wichtigsten ist die Möglichkeit, eine Versionierung der verschiedenen Änderungen des Datenbankschemas zu ermöglichen. Ohne die Migrationen wären diese Schemaänderungen inkohärent und könnten nicht nachverfolgt werden, was zu Versionierungsproblemen und möglichen Fehlern führen würde.
Rollback: Für den Fall eines Fehlers ist immer ein Rollback-System erforderlich. Ein Migrationssystem verfügt immer über zwei Methoden: oben, um die Änderungen in der Datenbank anzuwenden, und unten, um die Änderungen schnell und konsistent rückgängig zu machen :-)
Automatisierung und CI/CD-Integration: Migrationen können automatisiert werden, sodass sie Teil der CI/CD-Pipeline sein können. Dies hilft bei der reibungslosen und konsistenten Bereitstellung von Änderungen ohne manuellen Eingriff.
Wir können noch viele weitere Vorteile finden, aber ich denke, diese Punkte stellen eine gute Zusammenfassung der Hauptvorteile dar.
Wie implementiert man Migrationen in Golang?
Go unterstützt Migrationen aus diesem Grund nicht nativ, daher können wir das beliebte Paket golang-migrate verwenden. Auch wenn Sie ein ORM wie GORM verwenden, können Sie es dafür verwenden.
Beide Pakete sind sehr beliebt, aber in diesem Beispiel verwende ich golang-migrate, da ich kein Interesse an der Implementierung eines ORM habe.
Zeig mir den Code!
Sehen wir uns Schritt für Schritt an, wie eine einfache Anwendung implementiert wird, um zu sehen, wie sie verwendet wird.
Um diesem Artikel folgen zu können, benötigen Sie: Go und Docker mit Docker Compose
Infrastruktur
Erstellen Sie die Datei docker-compose.yml in Ihrem Stammverzeichnis, in dem wir Ihre Lieblings-DB definieren. In meinem Fall verwenden Sie eine MariaDB, Sie können aber auch gerne eine andere verwenden.
services: mariadb: image: mariadb:11.5.2 container_name: mariadb_example_go_migration ports: - "3306:3306" environment: - MYSQL_DATABASE=app - MYSQL_ROOT_PASSWORD=root - TZ=Europe/Berlin volumes: - mariadbdata:/var/lib/mysql volumes: mariadbdata: driver: local docker compose up -d
Wenn Sie möchten, können Sie Docker direkt anstelle von Docker-Compose verwenden:
docker volume create -d local mariadbdata docker run --name mariadb_example_go_migration -p 3306:3306 -e MYSQL_DATABASE=app -e MYSQL_ROOT_PASSWORD=root -e TZ=Europe/Berlin -v mariadbdata:/var/lib/mysql mariadb:11.5.2
Umweltwerte
Erstellen oder aktualisieren Sie die Datei .env in Ihrem Stammverzeichnis, in dem Sie die Variablen definieren müssen, um unsere Datenbank zu verbinden.
DATABASE_DSN=root:root@tcp(localhost:3306)/app
Erstellen Sie eine einfache Golang-App
Erstellen Sie eine einfache Golang-Anwendung, um eine erfolgreiche DB-Verbindung sicherzustellen und alle Tabellen und Strukturen in der Datenbank mit ihrer Struktur aufzulisten. cmd/main.go
package main import ( "database/sql" "fmt" "log" "os" "text/tabwriter" _ "github.com/go-sql-driver/mysql" "github.com/joho/godotenv" ) func main() { // Load .env variables err := godotenv.Load() if err != nil { log.Fatal("Error loading .env file") } // Open connection with MySQL DB db, err := sql.Open("mysql", os.Getenv("DATABASE_DSN")) if err != nil { log.Fatalf("Error opening database: %v\n", err) } defer db.Close() // Ensure that the connection works err = db.Ping() if err != nil { log.Fatalf("Error connecting database: %v\n", err) } fmt.Println("Connected to database") // Execute the SHOW TABLES query to list all tables in the database tables, err := db.Query("SHOW TABLES") if err != nil { log.Fatalf("Failed to execute SHOW TABLES query: %v\n", err) } defer tables.Close() fmt.Println("Database structure:") for tables.Next() { var tableName string if err := tables.Scan(&tableName); err != nil { log.Fatalf("Failed to scan table name: %v\n", err) } w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', tabwriter.Debug) fmt.Printf("\n[Table: %s]\n\n", tableName) fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t\n", "Field", "Type", "Null", "Key", "Default", "Extra") // Get the structure of the current table structureQuery := fmt.Sprintf("DESCRIBE %s", tableName) columns, err := db.Query(structureQuery) if err != nil { log.Fatalf("Failed to describe table %s: %v\n", tableName, err) } defer columns.Close() for columns.Next() { var field, colType, null, key, defaultVal, extra sql.NullString err := columns.Scan(&field, &colType, &null, &key, &defaultVal, &extra) if err != nil { log.Fatalf("Failed to scan column: %v\n", err) } fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t\n", field.String, colType.String, null.String, key.String, defaultVal.String, extra.String) } w.Flush() } }
Und wenn wir es ausführen, erhalten wir eine ähnliche Ausgabe:
CLI migrieren
Um die Golang-Migrate-CLI auszuführen, haben Sie grundsätzlich zwei Methoden: Installieren Sie die CLI lokal oder führen Sie sie über das offizielle Docker-Image aus: migrieren/migrieren.
Persönlich bevorzuge ich die Docker-Variante, aber in diesem Tutorial werden beide Varianten veranschaulicht.
So generieren Sie eine Migration
Der erste Schritt besteht darin, mit dem nächsten Befehl eine leere Migration zu erstellen.
services: mariadb: image: mariadb:11.5.2 container_name: mariadb_example_go_migration ports: - "3306:3306" environment: - MYSQL_DATABASE=app - MYSQL_ROOT_PASSWORD=root - TZ=Europe/Berlin volumes: - mariadbdata:/var/lib/mysql volumes: mariadbdata: driver: local docker compose up -d
docker volume create -d local mariadbdata docker run --name mariadb_example_go_migration -p 3306:3306 -e MYSQL_DATABASE=app -e MYSQL_ROOT_PASSWORD=root -e TZ=Europe/Berlin -v mariadbdata:/var/lib/mysql mariadb:11.5.2
- ext: Erweiterung der zu generierenden Datei.
- dir: Verzeichnis, in dem unsere Migration erstellt wird.
- seq: Name der Migrationssequenz.
Dieser Befehl generiert zwei leere Dateien im Ordner „database/migrations/“: 000001createuserstable.up.sql und 000001createuserstable.down.sql
In der Datei 000001createuserstable.up.sql definieren Sie SQL zum Erstellen einer Tabelle für Benutzer:
DATABASE_DSN=root:root@tcp(localhost:3306)/app
In der Datei 000001createuserstable.down.sql definieren Sie SQL, um alle von up vorgenommenen Änderungen rückgängig zu machen. In diesem Fall müssen wir die Benutzertabelle löschen:
package main import ( "database/sql" "fmt" "log" "os" "text/tabwriter" _ "github.com/go-sql-driver/mysql" "github.com/joho/godotenv" ) func main() { // Load .env variables err := godotenv.Load() if err != nil { log.Fatal("Error loading .env file") } // Open connection with MySQL DB db, err := sql.Open("mysql", os.Getenv("DATABASE_DSN")) if err != nil { log.Fatalf("Error opening database: %v\n", err) } defer db.Close() // Ensure that the connection works err = db.Ping() if err != nil { log.Fatalf("Error connecting database: %v\n", err) } fmt.Println("Connected to database") // Execute the SHOW TABLES query to list all tables in the database tables, err := db.Query("SHOW TABLES") if err != nil { log.Fatalf("Failed to execute SHOW TABLES query: %v\n", err) } defer tables.Close() fmt.Println("Database structure:") for tables.Next() { var tableName string if err := tables.Scan(&tableName); err != nil { log.Fatalf("Failed to scan table name: %v\n", err) } w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', tabwriter.Debug) fmt.Printf("\n[Table: %s]\n\n", tableName) fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t\n", "Field", "Type", "Null", "Key", "Default", "Extra") // Get the structure of the current table structureQuery := fmt.Sprintf("DESCRIBE %s", tableName) columns, err := db.Query(structureQuery) if err != nil { log.Fatalf("Failed to describe table %s: %v\n", tableName, err) } defer columns.Close() for columns.Next() { var field, colType, null, key, defaultVal, extra sql.NullString err := columns.Scan(&field, &colType, &null, &key, &defaultVal, &extra) if err != nil { log.Fatalf("Failed to scan column: %v\n", err) } fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t\n", field.String, colType.String, null.String, key.String, defaultVal.String, extra.String) } w.Flush() } }
So wenden Sie die Migration an
Der folgende Befehl wendet alle ausstehenden Migrationen an. Sie können auch die Anzahl der anzuwendenden Migrationen definieren, indem Sie die Zahl nach dem Up hinzufügen.
#CLI variant migrate create -ext sql -dir ./database/migrations -seq create_users_table
#Docker CLI variant docker run --rm -v $(pwd)/database/migrations:/migrations migrate/migrate \ create -ext sql -dir /migrations -seq create_users_table
- Pfad: Pfad zum Migrationsverzeichnis.
- Datenbank: Definieren Sie Ihre Datenbank-DSN-Verbindung.
HINWEIS: Wenn die Migration zum ersten Mal ausgeführt wird, wird eine Tabelle „schema_migrations“ erstellt, in der die Migration die angewendete Versionsnummer kennt.
Und führen Sie unsere Golang-Anwendung aus, um die Ergebnisse anzuzeigen:
Neue Migration hinzufügen
Fügen Sie ein neues Spaltentelefon zur Benutzertabelle hinzu
CREATE TABLE `users` ( `id` VARCHAR(36) NOT NULL PRIMARY KEY, `name` VARCHAR(255) NOT NULL, `email` VARCHAR(255) NOT NULL UNIQUE, `password` VARCHAR(255) NOT NULL );
DROP TABLE IF EXISTS `users`;
#CLI variant migrate -path=./database/migrations -database "mysql://root:root@tcp(localhost:3306)/app" up
#Docker CLI variant docker run --rm -v $(pwd)/database/migrations:/migrations --network host migrate/migrate \ -path=/migrations -database "mysql://root:root@tcp(localhost:3306)/app" up
Und wenn Sie es über unsere Golang-Anwendung ausführen, sehen Sie das neue Feld:
So machen Sie die Migration rückgängig
Mit dem folgenden Befehl können wir die angewendeten Daten ganz einfach zurücksetzen. Migrationen. Im folgenden Beispiel können wir sehen, wie wir die zuletzt angewendete Migration rückgängig machen:
#CLI variant migrate create -ext sql -dir ./database/migrations -seq add_column_phone #Docker CLI variant docker run --rm -v $(pwd)/database/migrations:/migrations migrate/migrate \ create -ext sql -dir /migrations -seq add_column_phone
-- 000002_add_column_phone.up.sql ALTER TABLE `users` ADD `phone` VARCHAR(255) NULL;
WARNUNG: Wenn Sie die Anzahl der Migrationen nicht definieren, wird ROLLBACK auf ALLE MIGRATIONEN angewendet!
Und dann können wir zeigen, dass die letzte Migration rückgängig gemacht und das Telefonfeld entfernt wurde :-)
So beheben Sie Migrationsfehler
Wenn eine Migration Fehler enthält und ausgeführt wird, kann diese Migration nicht angewendet werden und das Migrationssystem verhindert weitere Migrationen in der Datenbank, bis diese Migration behoben ist.
Und wenn wir versuchen, uns zu bewerben, erhalten wir eine Nachricht wie diese:
services: mariadb: image: mariadb:11.5.2 container_name: mariadb_example_go_migration ports: - "3306:3306" environment: - MYSQL_DATABASE=app - MYSQL_ROOT_PASSWORD=root - TZ=Europe/Berlin volumes: - mariadbdata:/var/lib/mysql volumes: mariadbdata: driver: local docker compose up -d
Keine Panik, es ist nicht schwer, zu einem einheitlichen System zurückzukehren.
Zuerst müssen wir die beschädigte Migration beheben, in diesem Fall Version 2.
Sobald die Migration gelöst ist, müssen wir das System auf die letzte gültige Version zwingen, in diesem Fall Version 1.
docker volume create -d local mariadbdata docker run --name mariadb_example_go_migration -p 3306:3306 -e MYSQL_DATABASE=app -e MYSQL_ROOT_PASSWORD=root -e TZ=Europe/Berlin -v mariadbdata:/var/lib/mysql mariadb:11.5.2
DATABASE_DSN=root:root@tcp(localhost:3306)/app
Und jetzt können Sie die Migrationen problemlos erneut anwenden ;-)
Makefile
Um unsere Produktivität zu verbessern und die Verwendung dieser Befehle zu erleichtern, können wir Makefile verwenden. Unten sehen Sie die beiden Varianten: Native Client und Docker.
CLI-Variante
package main import ( "database/sql" "fmt" "log" "os" "text/tabwriter" _ "github.com/go-sql-driver/mysql" "github.com/joho/godotenv" ) func main() { // Load .env variables err := godotenv.Load() if err != nil { log.Fatal("Error loading .env file") } // Open connection with MySQL DB db, err := sql.Open("mysql", os.Getenv("DATABASE_DSN")) if err != nil { log.Fatalf("Error opening database: %v\n", err) } defer db.Close() // Ensure that the connection works err = db.Ping() if err != nil { log.Fatalf("Error connecting database: %v\n", err) } fmt.Println("Connected to database") // Execute the SHOW TABLES query to list all tables in the database tables, err := db.Query("SHOW TABLES") if err != nil { log.Fatalf("Failed to execute SHOW TABLES query: %v\n", err) } defer tables.Close() fmt.Println("Database structure:") for tables.Next() { var tableName string if err := tables.Scan(&tableName); err != nil { log.Fatalf("Failed to scan table name: %v\n", err) } w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', tabwriter.Debug) fmt.Printf("\n[Table: %s]\n\n", tableName) fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t\n", "Field", "Type", "Null", "Key", "Default", "Extra") // Get the structure of the current table structureQuery := fmt.Sprintf("DESCRIBE %s", tableName) columns, err := db.Query(structureQuery) if err != nil { log.Fatalf("Failed to describe table %s: %v\n", tableName, err) } defer columns.Close() for columns.Next() { var field, colType, null, key, defaultVal, extra sql.NullString err := columns.Scan(&field, &colType, &null, &key, &defaultVal, &extra) if err != nil { log.Fatalf("Failed to scan column: %v\n", err) } fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t\n", field.String, colType.String, null.String, key.String, defaultVal.String, extra.String) } w.Flush() } }
Docker-CLI-Variante
#CLI variant migrate create -ext sql -dir ./database/migrations -seq create_users_table
Repository
Der Code für dieses Tutorial ist öffentlich zu finden: GitHub – albertcolom/example-go-migration
Original veröffentlicht unter: albertcolom.com
Das obige ist der detaillierte Inhalt vonSo verwenden Sie Migrationen mit Golang. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen

GO Language Pack Import: Was ist der Unterschied zwischen Unterstrich und ohne Unterstrich?

Wie kann ich kurzfristige Informationsübertragung zwischen Seiten im BeEGO-Framework implementieren?

Wie konvertieren Sie die Liste der MySQL -Abfrageergebnisse in eine benutzerdefinierte Struktur -Slice in Go -Sprache?

Wie kann ich benutzerdefinierte Typ -Einschränkungen für Generika in Go definieren?

Wie schreibe ich Scheinobjekte und Stubs zum Testen in Go?

Wie schreibe ich Dateien in Go Language bequem?

Wie kann ich Tracing -Tools verwenden, um den Ausführungsfluss meiner GO -Anwendungen zu verstehen?
