ホームページ バックエンド開発 Golang Golang で移行を使用する方法

Golang で移行を使用する方法

Nov 09, 2024 am 07:28 AM

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()
 }
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

実行すると、同様の出力が得られます。

How to use migrations with Golang

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 アプリケーションを実行して結果を表示します。

How to use migrations with 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 アプリケーションから実行すると、新しいフィールドが表示されます:

How to use migrations with 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すべての移行 に適用されます!

そして、最後の移行が元に戻され、電話フィールドが削除されたことがわかります :-)

Display table users without phone field

移行エラーを解決する方法

移行にエラーが含まれて実行された場合、その移行は適用できず、移行システムは、この移行が修正されるまでデータベースでのさらなる移行を禁止します。

そして、適用しようとすると、次のようなメッセージが表示されます:

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 サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

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

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

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

Golang vs. Python:パフォーマンスとスケーラビリティ Golang vs. Python:パフォーマンスとスケーラビリティ Apr 19, 2025 am 12:18 AM

Golangは、パフォーマンスとスケーラビリティの点でPythonよりも優れています。 1)Golangのコンピレーションタイプの特性と効率的な並行性モデルにより、高い並行性シナリオでうまく機能します。 2)Pythonは解釈された言語として、ゆっくりと実行されますが、Cythonなどのツールを介してパフォーマンスを最適化できます。

Golang and C:Concurrency vs. Raw Speed Golang and C:Concurrency vs. Raw Speed Apr 21, 2025 am 12:16 AM

Golangは並行性がCよりも優れていますが、Cは生の速度ではGolangよりも優れています。 1)Golangは、GoroutineとChannelを通じて効率的な並行性を達成します。これは、多数の同時タスクの処理に適しています。 2)Cコンパイラの最適化と標準ライブラリを介して、極端な最適化を必要とするアプリケーションに適したハードウェアに近い高性能を提供します。

Golangの影響:速度、効率、シンプルさ Golangの影響:速度、効率、シンプルさ Apr 14, 2025 am 12:11 AM

speed、効率、およびシンプル性をspeedsped.1)speed:gocompilesquilesquicklyandrunseffictient、理想的なlargeprojects.2)効率:等系dribribraryreducesexexternaldedenciess、開発効果を高める3)シンプルさ:

ゴーを始めましょう:初心者のガイド ゴーを始めましょう:初心者のガイド Apr 26, 2025 am 12:21 AM

goisidealforforbeginnersandsutable forcloudnetworkservicesduetoitssimplicity、andconcurrencyfeatures.1)installgofromtheofficialwebsiteandverify with'goversion'.2)

Golang vs. C:パフォーマンスと速度の比較 Golang vs. C:パフォーマンスと速度の比較 Apr 21, 2025 am 12:13 AM

Golangは迅速な発展と同時シナリオに適しており、Cは極端なパフォーマンスと低レベルの制御が必要なシナリオに適しています。 1)Golangは、ごみ収集と並行機関のメカニズムを通じてパフォーマンスを向上させ、高配列Webサービス開発に適しています。 2)Cは、手動のメモリ管理とコンパイラの最適化を通じて究極のパフォーマンスを実現し、埋め込みシステム開発に適しています。

Golang vs. Python:重要な違​​いと類似点 Golang vs. Python:重要な違​​いと類似点 Apr 17, 2025 am 12:15 AM

GolangとPythonにはそれぞれ独自の利点があります。Golangは高性能と同時プログラミングに適していますが、PythonはデータサイエンスとWeb開発に適しています。 Golangは同時性モデルと効率的なパフォーマンスで知られていますが、Pythonは簡潔な構文とリッチライブラリエコシステムで知られています。

GolangとC:パフォーマンスのトレードオフ GolangとC:パフォーマンスのトレードオフ Apr 17, 2025 am 12:18 AM

GolangとCのパフォーマンスの違いは、主にメモリ管理、コンピレーションの最適化、ランタイム効率に反映されています。 1)Golangのゴミ収集メカニズムは便利ですが、パフォーマンスに影響を与える可能性があります。

CとGolang:パフォーマンスが重要な場合 CとGolang:パフォーマンスが重要な場合 Apr 13, 2025 am 12:11 AM

Cは、ハードウェアリソースと高性能の最適化が必要なシナリオにより適していますが、Golangは迅速な開発と高い並行性処理が必要なシナリオにより適しています。 1.Cの利点は、ハードウェア特性と高い最適化機能に近いものにあります。これは、ゲーム開発などの高性能ニーズに適しています。 2.Golangの利点は、その簡潔な構文と自然な並行性サポートにあり、これは高い並行性サービス開発に適しています。

See all articles