Golang で移行を使用する方法
golang-mite の使用方法を示す簡単なサンプル アプリケーション
なぜ移行を使用する必要があるのでしょうか?
多くの人がこの質問をするので、移行の使用に関する主な利点を強調するためにこのリストを作成してみました。
バージョン管理: 主要かつ最も重要なことの 1 つは、データベース スキーマのさまざまな変更のバージョン管理ができることです。移行がなければ、これらのスキーマ変更は一貫性がなく追跡不可能となり、バージョン管理の問題やエラーが発生する可能性があります。
ロールバック: 障害が発生した場合に備えて、ロールバック システムが常に必要です。移行システムには常に、データベースに変更を適用するためのメソッドと、変更を迅速かつ一貫して元に戻すためのメソッドが 2 つあります:-)
自動化と CI/CD の統合: 移行を自動化して、CI/CD パイプラインの一部にすることができます。これは、手動介入なしで変更をスムーズかつ一貫してデプロイするのに役立ちます。
他にも多くの利点を見つけることができますが、これらの点が主な利点の適切な要約を表していると思います。
Golang で移行を実装するにはどうすればよいですか?
Go はそのプロジェクトの移行をネイティブにサポートしていないため、人気のある golang-Migrate パッケージを使用できます。また、GORM などの ORM を使用している場合は、それを使用できます。
どちらのパッケージも非常に人気がありますが、ORM の実装には興味がないので、この例では golang-maigrate を使用します。
コードを見せてください!
簡単なアプリケーションを実装し、それがどのように使用されるかを段階的に見てみましょう。
この記事を進めるには次のものが必要です: Go と Docker Compose を使用した Docker
インフラストラクチャー
ルート ディレクトリにファイル docker-compose.yml を作成します。ここでお気に入りの DB を定義します。私の場合は MariaDB を使用しますが、別の DB を自由に使用してください。
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-compose の代わりに Docker を直接使用することもできます。
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
環境値
データベースに接続するための変数を定義する必要があるルート ディレクトリでファイル .env を作成または更新します。
DATABASE_DSN=root:root@tcp(localhost:3306)/app
簡単な golang アプリを作成する
シンプルな golang アプリケーションを作成して、DB 接続を成功させ、データベース内のすべてのテーブルと構造をその構造とともにリストします。 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() } }
実行すると、同様の出力が得られます。
CLIの移行
golang-merge CLI を実行するには、基本的に、CLI をローカルにインストールするか、公式の Docker イメージを介して実行する 2 つの方法があります: 移行/移行。
個人的には Docker バリアントの方が好きですが、このチュートリアルでは両方のバリアントを説明します。
移行を生成する方法
最初のステップは、次のコマンドで空の移行を作成することです。
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: 生成されるファイルの拡張子。
- dir: 移行が作成されるディレクトリ。
- seq: 移行シーケンス名。
このコマンドは、database/migrations/ フォルダーに 2 つの空のファイル、000001createuserstable.up.sql および 000001createuserstable.down.sql を生成します
000001createuserstable.up.sql ファイルで、テーブル ユーザーを作成するための SQL を定義します。
DATABASE_DSN=root:root@tcp(localhost:3306)/app
000001createuserstable.down.sql ファイルで、up によって行われたすべての変更を元に戻す SQL を定義します。この場合、users テーブルを削除する必要があります。
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() } }
移行の適用方法
次のコマンドは、保留中のすべての移行を適用します。 up の後に数値を追加することで、適用する移行の数を定義することもできます。
#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
- path: 移行ディレクトリへのパス。
- データベース: データベース DSN 接続を定義します。
注 : 初めて移行を実行するとき、移行が適用されるバージョン番号を認識するテーブル「schema_migrations」が作成されます。
そして、Golang アプリケーションを実行して結果を表示します。
新しい移行の追加
users テーブルに新しい列電話を追加します
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
Golang アプリケーションから実行すると、新しいフィールドが表示されます:
移行を元に戻す方法
次のコマンドを使用すると、適用されたものを簡単にロールバックできます。移住。次の例では、最後に適用された移行を元に戻す方法を確認できます。
#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;
警告 : 移行の数を定義しない場合、ROLLBACK が すべての移行 に適用されます!
そして、最後の移行が元に戻され、電話フィールドが削除されたことがわかります :-)
移行エラーを解決する方法
移行にエラーが含まれて実行された場合、その移行は適用できず、移行システムは、この移行が修正されるまでデータベースでのさらなる移行を禁止します。
そして、適用しようとすると、次のようなメッセージが表示されます:
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
パニックにならないでください。一貫したシステムに戻すのは難しくありません。
まず、破損した移行 (この場合はバージョン 2) を解決する必要があります。
移行が解決したら、システムを強制的に最後の有効なバージョン、この場合はバージョン 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
これで、問題なく移行を再適用できるようになりました ;-)
メイクファイル
生産性を向上させ、これらのコマンドの使用を容易にするために、Makefile を使用できます。以下に、ネイティブ クライアントと Docker の 2 つのバリエーションを示します。
CLI バリアント
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 のバリアント
#CLI variant migrate create -ext sql -dir ./database/migrations -seq create_users_table
リポジトリ
このチュートリアルのコードは、GitHub - albertcolom/example-go-migration で公開されています
原文の公開場所: albertcolom.com
以上がGolang で移行を使用する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











Go Language Packのインポート:アンダースコアとアンダースコアなしの違いは何ですか?

MySQLクエリ結果リストをGO言語のカスタム構造スライスに変換する方法は?

GOのジェネリックのカスタムタイプ制約を定義するにはどうすればよいですか?

GOでテスト用のモックオブジェクトとスタブを書くにはどうすればよいですか?

トレースツールを使用して、GOアプリケーションの実行フローを理解するにはどうすればよいですか?
