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. 最大1つのフィールド: oneofフィールドを設定すると、グループ内の以前に設定されたフィールドが自動的にクリアされます。
  2. ケース検出: 生成されたコードには、現在どのフィールドが設定されているかを判定するwhich_*または*_case()メソッドが含まれます。
  3. メモリ共有: C++ではoneof内のすべてのフィールドがメモリを共有し、メッセージのメモリフットプリントを削減します。
  4. 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フィールド。

試してみる — Protobuf Definition Parser

フルツールを開く