Open8

protocol buffers入門

tenryutenryu

Prorocol Buffersとは

Googleが開発したデータフォーマット。定義したスキーマをシリアライズ&デシリアライズする機能を持つ。

主な利点は3つ

  • データをシリアライズすることで、jsonやxmlよりも軽量&高速にデータをやり取りすることができる
  • スキーマを.protoファイルで定義し、PythonやGoなど様々言語でやり取りするためのコードを生成することができる
  • スキーマに変更があっても問題ないような後方互換性を持つことができる

https://qiita.com/nozmiz/items/fdbd052c19dad28ab067

tenryutenryu

Tag

シリアライズ化する際の基準となる。以下でいうと1,2,3...のように振られている番号。

message Account {
  uint32 id = 1;
  string name = 2;
  bytes thumbnail = 3;
  bool is_verified = 4;
  float height = 5;
}
tenryutenryu

同じファイルで複数メッセージを定義

syntax = "proto3";

message MessageOne {

}

enum EnumOne {
  ENUM_ONE_UNSPECIFIED = 0;
}

message MessageTwo {
  MessageOne one = 1;
  EnumOne two = 2;
}
tenryutenryu

package

別ファイルの定義を使用

パッケージ
syntax = "proto3";

package my.package;

message MessageSix {
  
}
利用側
syntax = "proto3";

// 同じディレクトリのpackage.protoを使用
import "package.proto";

message MessageSeven {
  my.package.MessageSix six = 1;
}

tenryutenryu

oneof

どれか一つのパラメータを許容する

.proto
syntax = "proto3";

package example.oneofs;

option go_package = "example.com/m/proto";

message Result {
  oneof result {
    string message = 1;
    uint32 id = 2;
  }
}
main.go
func doOneOf(message interface{}) {
	switch x := message.(type) {
	case *pb.Result_Id:
		fmt.Println(message.(*pb.Result_Id).Id)
	case *pb.Result_Message:
		fmt.Println(message.(*pb.Result_Message).Message)
	default:
		fmt.Errorf("message had unexpected type: %v", x)
	}
}

func main() {
	doOneOf(&pb.Result_Id{Id: 42})
	doOneOf(&pb.Result_Message{Message: "a message"})
}
tenryutenryu

reserved

後方互換性を保つための仕組みとしてreservedがある。
以下の場合、3と10から20のタグ、フィールド名としてold_emailとold_phone_numberは使用できない、という制約を設けることができる。将来的な変更があった場合、これらの制約を設けることで互換性の問題を避けることができる。

syntax = "proto3";

message UserProfile {
    reserved 3, 10 to 20;
    reserved "old_email", "old_phone_number";

    string name = 1;
    int32 age = 2;
    string email = 4;
}

以下のように制約を破ってビルドしてみるとエラーになる。

syntax = "proto3";

package example.enumarations;

option go_package = "example.com/m/proto";

enum EyeColor {
  EYE_COLOR_UNSPECIFIED = 0;
  EYE_COLOR_GREEN = 1;
  EYE_COLOR_BLUE = 2;
  EYE_COLOR_BROWN = 3;
}

message Enumuration {
  reserved 2;
  EyeColor eye_color = 1;
  bool is_simple = 2;
}
protoc -Iproto --go_opt=module=example.com/m --go_out=. proto/*.proto
enumurations.proto: Field "is_simple" uses reserved number 2.
make: *** [generate] Error 1