web-dev-qa-db-ja.com

プロトコルバッファ-一意の番号付きタグ-説明?

私はプロトコルバッファを使用していますが、すべてが正常に機能しています。私が理解していないという事実を除いて-なぜ私はprotoファイルに番号付きタグが必要なのですか?

message SearchRequest {
  required string query = 1;
  optional int32 page_number = 2;
  optional int32 result_per_page = 3;
}

確かに私は docs を読みました:

ご覧のとおり、メッセージ定義の各フィールドには一意の番号付きタグがあります。これらのタグは、メッセージバイナリ形式でフィールドを識別するために使用され、メッセージタイプが使用された後は変更しないでください。

変更するとどうなるのかわかりませんでした。 (私は新しいプロトを作成してコンパイルします-それでなぜそれが気になるのですか?)

別の記事では:

プロト定義の番号付きフィールドにより、バージョンチェックが不要になります。これは、プロトコルバッファの設計と実装について明確に述べられている動機の1つです。開発者向けドキュメントに記載されているように、プロトコルは、プロトコルのバージョンをチェックするためのこのような「醜いコード」を回避するように部分的に設計されています。

if (version == 3) {
  ...
} else if (version > 4) {
  if (version == 5) {
    ...
  }
  ...
}

質問

それは私だけですか、それとも完全に不明ですか?

別の方法で聞いてみましょう:

上記のファイルのようなプロトファイルがある場合は、次のように変更します。

message SearchRequest {
  required string query = 3; //reversed order
  optional int32 page_number = 2;
  optional int32 result_per_page = 1;
}

それは何を気にしますか?ファイルを再コンパイルして追加します(先週、何度も実行しました)。

私は何が欠けていますか?この番号付きタグについて、人から人への説明を提供していただけますか?

29
Royi Namir

番号付きのタグは、データをシリアル化および逆シリアル化するときにフィールドを照合するために使用されます。

明らかに、番号付けスキームを変更し、この変更をシリアライザーとデシリアライザーの両方に適用する場合、問題はありません。

ただし、最初の番号付けスキームでデータを保存し、2番目の番号付けスキームでデータをロードした場合、queryresult_per_pageにロードしようとし、逆シリアル化が失敗する可能性があります。

さて、なぜこれが便利なのですか?スキーマがすでに使用されているずっと後に、データに別のフィールドを追加する必要があるとしましょう。

message SearchRequest {
  required string query = 1;
  optional int32 page_number = 2;
  optional int32 result_per_page = 3;
  optional int32 new_data = 4;
}

明示的に番号を指定するため、デシリアライザーは、存在しないデータのデシリアライズを無視して、oldナンバリングスキームでシリアル化されたデータをロードできます。

25
Rotem

これらのフィールド番号は、エンコードおよびデコード中にprotobufによって使用されます。詳細については、 ここ を参照してください。

したがって、すべてのフィールドにはワイヤタイプがあるため、int32のワイヤタイプは0で、フィールド番号は2であるため、0001 0000、つまり16進数で10としてエンコードされます。

その後、デコードされると、左に1シフトされ、001 0000になり、最後の3つのlsbがワイヤタイプを決定します。つまり、intフィールドのタイプを決定し、restがprotoのどのフィールドであるかを決定します。つまり、000010は2です。ワイヤタイプ0のフィールド2(int)

3
SMA