コマンドラインツール
インストール、使用法、ベストプラクティスを含め、Goaのコード生成用コマンドラインツールについて学びます。
Goaのコード生成システムは、あなたのデザインを本番環境対応のコードに変換します。 単なるスキャフォールディングではなく、Goaはベストプラクティスに従い、API全体で 一貫性を維持する完全な、実行可能なサービス実装を生成します。
Goaのコード生成は、デザインファイルを取り込み、完全な、実行可能なサービス実装を生成します。
Goaのコマンドラインツールを以下のようにインストールします:
go install goa.design/goa/v3/cmd/goa@latest
Goaは、サービスを生成しスキャフォールディングするための2つのコマンドを提供します。 すべてのコマンドはファイルシステムのパスではなく、Goパッケージのインポートパスを 期待します:
# ✅ 正しい:Goパッケージのインポートパスを使用
goa gen goa.design/examples/calc/design
# ❌ 誤り:ファイルシステムのパスを使用
goa gen ./design
goa gen
)goa gen <design-package-import-path> [-o <output-dir>]
コード生成のための主要なコマンドです。以下を行います:
gen/
ディレクトリを最初から再作成-o
フラグで出力場所をカスタマイズ可能(デフォルトは./gen
)goa example
)goa example <design-package-import-path> [-o <output-dir>]
スキャフォールディングコマンドで、以下を行います:
goa version
)goa version
インストールされているGoaのバージョンを表示します。
Goaのコード生成コマンドを実行すると、Goaは以下の体系的なプロセスに従って デザインを動作するコードに変換します:
生成プロセスはいくつかのフェーズで行われます:
ブートストラップ:
まず、GoaはデザインパッケージとGoaパッケージをインポートする一時的なmain.go
ファイルを作成します。この一時ファイルはコード生成をブートストラップするために
別プロセスとしてコンパイルされ実行されます。
DSLの実行: デザインパッケージの初期化関数が最初に実行され、続いてDSL関数が実行されて メモリ内に式オブジェクトを構築します。これらの式は協調して、API設計全体を 表す包括的なモデルを作成します。
バリデーション: バリデーション中、Goaは式ツリーが完全で適切に形成されていることを確認する 包括的なチェックを実行します。式間の必要な関係がすべて適切に定義されており、 デザインがすべてのルールと制約に従っていることを検証します。このバリデーション ステップは、コードが生成される前に潜在的な問題を早期に発見するのに役立ちます。
コード生成:
バリデーションが完了すると、Goaは有効な式をコードジェネレーターに渡します。
これらのジェネレーターは式データを使用してテンプレートをレンダリングし、
実際のコードファイルを生成します。生成されたファイルは、サービスとトランス
ポート層ごとに整理されて、プロジェクトのgen/
ディレクトリに書き込まれます。
Meta
関数を使用してコード生成の動作をカスタマイズできます。以下は生成に影響を
与える主要なメタデータタグです:
"type:generate:force"
タグを使用すると、メソッドから直接参照されていない場合でも
型の生成を強制できます。値は型を生成する必要のあるサービスの名前です。
var MyType = Type("MyType", func() {
// 未使用でも型の生成を強制
Meta("type:generate:force", "service1", "service2")
Attribute("name", String)
})
"struct:pkg:path"
タグを使用すると、型のパッケージとパスを指定できます。値は
gen
パッケージからの相対パッケージパスです。
var MyType = Type("MyType", func() {
// カスタムパッケージで型を生成
Meta("struct:pkg:path", "types")
})
var MyStruct = Struct("MyStruct", func() {
Attribute("ssn", String, func() {
// フィールド名を上書き
Meta("struct:field:name", "SSN")
// カスタム構造体タグ
Meta("struct:tag:json", "ssn,omitempty")
})
})
"struct:name:proto"
タグを使用すると、型のプロトコルバッファーメッセージの名前を
指定できます。値はパッケージパス、メッセージ名、およびプロトコルバッファー型の
インポートパスです。
var Timestamp = Type("Timestamp", func() {
// protobufメッセージ名を上書き
Meta("struct:name:proto", "MyProtoType")
Field(1, "created_at", String, func() {
// Googleのタイムスタンプ型を使用
Meta("struct:field:proto",
"google.protobuf.Timestamp",
"google/protobuf/timestamp.proto",
"Timestamp",
"google.golang.org/protobuf/types/known/timestamppb")
})
})
"openapi:generate"
タグを使用すると、サービスのOpenAPI生成を無効にできます。
値は型を生成する必要のあるサービスの名前です。
"openapi:operationId"
タグを使用すると、メソッドの操作IDを指定できます。
値はサービス名とメソッド名です。
"openapi:tag"
タグを使用すると、サービスのOpenAPIタグを指定できます。
値はサービス名とタグ名です。
var _ = Service("MyService", func() {
// このサービスのOpenAPI生成を無効化
Meta("openapi:generate", "false")
Method("MyMethod", func() {
// カスタム操作ID
Meta("openapi:operationId", "{service}.{method}")
// OpenAPIタグを追加
Meta("openapi:tag:Backend", "バックエンドAPI")
})
})
一般的なメタデータの用途:
type:generate:force
を使用struct:pkg:path
)を維持Goaのプラグインシステムを使用すると、コード生成プロセスを拡張およびカスタマイズ できます。プラグインは生成パイプラインの特定のポイントで介入し、機能の追加、生成 されたコードの変更、または完全に新しい出力の作成を可能にします。
プラグインは以下の3つの主要な方法でGoaと対話できます:
var _ = Service("calc", func() {
Description("電卓サービス")
// CORSプラグインが追加するDSL
cors.Origin("/.*localhost.*/", func() {
cors.Headers("X-Shared-Secret")
cors.Methods("GET", "POST")
})
})
生成されたコードの変更
プラグインはGoaが生成するファイルを検査および変更したり、完全に新しいファイルを
追加したりできます:プラグインのGenerate
関数は、デザインが評価された後のコード
生成中にGoaによって呼び出されます。以下を受け取ります:
genpkg
:生成されたコードが配置されるGoパッケージパスroots
:すべてのデザインデータを含む評価済みのデザインルートfiles
:Goaがこれまでに生成したファイルの配列この関数により、プラグインは生成されたファイルを検査および変更し、出力に完全に 新しいファイルを追加し、生成からファイルを削除し、デザインに基づいてコードを 変換できます。この関数の柔軟性により、プラグインは最終的に生成されるコードベース を完全に制御できます。
プラグインは通常、以下のために使用されます:
既存のプラグインを使用するには:
goa gen
を実行 - プラグインは自動的に統合されますimport (
. "goa.design/goa/v3/dsl"
cors "goa.design/plugins/v3/cors/dsl"
)
これはGoaのプラグインシステムの概要に過ぎません。以下の詳細情報については:
プラグインセクションを参照してください。