ProtobufのOneofフィールド
oneofを使用してprotobufで相互排他的なフィールドを定義する方法。メモリ最適化、設定の動作、ユニオン型やポリモーフィズムの一般的なパターンを学びます。
Enums & Oneof
詳細な説明
Oneofによる相互排他的フィールド
oneof構造は、一度に最大1つのフィールドのみが設定できるフィールドのセットを定義します。oneofのいずれかのフィールドを設定すると、同じグループの他のすべてのフィールドが自動的にクリアされます。これはprotobufのユニオン型アプローチです。
syntax = "proto3";
message PaymentMethod {
string id = 1;
oneof method {
CreditCard credit_card = 2;
BankAccount bank_account = 3;
DigitalWallet digital_wallet = 4;
Cryptocurrency crypto = 5;
}
}
message CreditCard {
string number = 1;
string expiry_month = 2;
string expiry_year = 3;
string cardholder_name = 4;
}
message BankAccount {
string account_number = 1;
string routing_number = 2;
string bank_name = 3;
}
message DigitalWallet {
string provider = 1;
string wallet_id = 2;
}
message Cryptocurrency {
string currency = 1;
string wallet_address = 2;
string network = 3;
}
Oneofの仕組み
- 最大1つのフィールド: oneofフィールドを設定すると、グループ内の以前に設定されたフィールドが自動的にクリアされます。
- ケース検出: 生成されたコードには、現在どのフィールドが設定されているかを判定する
which_*または*_case()メソッドが含まれます。 - メモリ共有: C++ではoneof内のすべてのフィールドがメモリを共有し、メッセージのメモリフットプリントを削減します。
- repeatedと併用不可: oneofフィールドで
repeatedは使用できません。
一般的なパターン
ポリモーフィックメッセージ — コンセプトの異なるバリアントの表現:
message Shape {
oneof shape {
Circle circle = 1;
Rectangle rectangle = 2;
Triangle triangle = 3;
}
}
結果型 — 成功または失敗の表現:
message OperationResult {
oneof result {
SuccessResponse success = 1;
ErrorResponse error = 2;
}
}
ワイヤーフォーマット
ワイヤー上では、oneofは通常のフィールドとしてエンコードされます。設定されたフィールドのみが現れます。受信側はフィールド番号を使用してどのバリアントが送信されたかを判断します。
ユースケース
支払い方法の選択、通知チャネルルーティング(メール vs SMS vs プッシュ)、認証資格情報タイプの実装、またはいくつかのオプションのうち正確に1つを提供する必要があるAPIフィールド。