Goaはバリデーションに対して実用的なアプローチを取り、パフォーマンスと堅牢性の バランスを取ります。フレームワークはシステムの境界でデータを検証し、内部操作は 信頼します:
このアプローチにより、内部操作の不要な検証オーバーヘッドを避けながら、コードが 常に有効なデータを受け取ることを保証します。
Goaのコード生成アルゴリズムは、構造体のフィールドでポインタをいつ使用するかを 慎重に考慮します。目標は、型の安全性と適切なnull処理を維持しながら、ポインタの 使用を最小限に抑えることです。
Goaがコードを生成する際、生成される構造体でフィールドをどのように表現するかに
ついて決定を下す必要があります。主要な決定の1つは、プリミティブ型(string
、
int
、bool
など)に対してポインタ(*)を使用するか、直接値(-)を使用するか
です。
ルールに深入りする前に、主要な用語を明確にしましょう:
ペイロード/結果: これらはサービスデザインにおけるメソッドの引数と戻り値です
method (payload *CreateUserPayload)
)returns (UserResult)
)リクエスト/レスポンスボディ: これらはHTTPまたはgRPCのトランスポートレベルの構造です
例えば、REST APIでは:
// デザインで:
var _ = Service("users", func() {
Method("create", func() {
Payload(func() {
Field(1, "name", String) // これはペイロードフィールド
Required("name")
})
Result(func() {
Field(1, "id", Int) // これは結果フィールド
})
HTTP(func() {
POST("/users")
Response(StatusOK)
})
})
})
// Goaが生成:
type CreatePayload struct {
Name string // ペイロードフィールド
}
type CreateRequestBody struct {
Name *string // リクエストボディフィールド
}
type CreateResult struct {
ID int // 結果フィールド
}
type CreateResponseBody struct {
ID int // レスポンスボディフィールド
}
ルールは以下によって異なります:
詳細な内訳は以下の通りです:
プロパティ | ペイロード/結果 | リクエストボディ(サーバー) | レスポンスボディ(サーバー) | リクエストボディ(クライアント) | レスポンスボディ(クライアント) |
---|---|---|---|---|---|
必須またはデフォルト値あり | 直接値(-) | ポインタ(*) | 直接値(-) | 直接値(-) | ポインタ(*) |
必須でない、デフォルト値なし | ポインタ(*) | ポインタ(*) | ポインタ(*) | ポインタ(*) | ポインタ(*) |
例を使って説明しましょう:
必須またはデフォルト値を持つフィールド:
name string
フィールドはName string
として生成されますオプションのフィールド(必須でない、デフォルト値なし):
age int
フィールドはAge *int
として生成されます特殊な型:
[]string
またはmap[string]int
(*[]string
や*map[string]int
ではない)これらのルールの理由:
例のシナリオ:
// 以下のフィールドを持つデザインの場合:
// - name: string(必須)
// - age: int(オプション)
// - hobbies: []string
// - metadata: map[string]string
// サービスパッケージで生成される構造体は以下のようになります:
type Person struct {
Name string // 必須、直接値
Age *int // オプション、ポインタ
Hobbies []string // 配列、ポインタなし
Metadata map[string]string // マップ、ポインタなし
}
デザインで指定されたデフォルト値は、2つの主要なシナリオで使用されます:
出力用にデータをマーシャリングする際、デフォルト値はnil値の処理で重要な役割を 果たします。nilである配列とマップフィールドの場合、デザインで指定された デフォルト値を使用して初期化されます。ただし、これはプリミティブフィールドには 適用されません - プリミティブフィールドは常にゼロ値(数値の場合は0、文字列の 場合は"“など)を持つためです。
受信データをアンマーシャリングする際、デフォルト値は入力に存在しないオプション フィールドにのみ適用されます。必須フィールドが欠けている場合、デフォルト値を 適用する代わりにバリデーションエラーが発生します。gRPCの場合、アンマーシャリング 時のデフォルト値の特別な処理があります - 詳細についてはgRPCアンマーシャリング セクションを参照してください。