Help us understand the problem. What is going on with this article?

Protocol Buffers 導入メモ Mac/Win

ProtocolBuffers

  • 通信や永続化での利用を目的としたシリアライズフォーマット
  • Googleによって開発されている
  • オープンソースライセンス
  • 多数言語(Java, Python, Objective-C, and C++...)に対応している

JSONや、MessagePackの様につかえる...!!

参考
Protocol Buffers  |  Google Developers
Protocol Buffers - Wikipedia

環境

  • macOS High Sierra
  • Windows 10

手順

  1. protoc を入手
  2. protoファイルを作成
  3. protoc コマンドで言語ごとに使用するファイルを出力
  4. 言語ごとにシリアライズ、デシリアライズ時に上記ファイルを使用

1. Protoc を入手

Mac

Homebrew経由で入手

# terminal等
$ brew update     # formula を更新
$ brew upgrade    # 更新があるパッケージを再ビルドする
$ brew install protobuf # protobufをインストール
$ brew upgrade protobuf # protobufをアップグレード

$ protoc --version
libprotoc 3.6.0

参考
homebrewでprotobufを最新版(3.0.0)にアップグレードする

Win

ここから、protoc-xxx-win32.zipを入手。
C:\Program Files\にProtocフォルダを作って上記zipを解答。
環境変数のPathに C:\Program Files\Protoc\protoc-3.4.0-win32\binを設定。

# powershell等
> protoc --version
libprotoc 3.6.0

(より良い方法があったら教えてくださいm(__)m)

2. protoファイルを作成

Person.proto
message Person {
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }

  repeated PhoneNumber phone = 4;
}

上記は公式のサンプルです。

  • required/optionalを定義できる
  • enumを使うことができる
  • messageフィールドで定義した他のmessageを使うことができる(上記では"PhoneNumber")
  • repeatedで繰り返し(配列)を定義できる。
message {
    TYPE NAME = UNIQUE NUMBER
}

が基本形のようです。
詳しくは、公式をチェックしてください
Language Guide (proto3)  |  Protocol Buffers  |  Google Developers

今回は、以下の簡単なexample.protoを使用します。

example.proto
syntax = "proto3";
package example;

message User {
    int32 id = 1;
    string name = 2;
}

3. protoc コマンドで言語ごとに使用するファイルを出力

go言語の場合は、
go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
を先に行ってください。 protocコマンドが裏側でprotoc-gen-goを使用しているみたいです。

protocコマンドを使ってファイルを出力します。
protoc --go_out=. -I. example.proto

  • example.pb.go

が出来上がっていると思います。
--xx_out= => xxが言語名、=の後ろにアウトプットしたいパス
-I => インプットフォルダのパス 
詳しくは、
protoc --help
をご確認下さい。

4. 言語ごとにシリアライズ、デシリアライズ時に上記ファイルを使用

ただ、シリアライズして、デシリアライズするシンプルなサンプルを以下に置いておきます。

フォルダ構成

.
├── main.go
└── protos
    └── example.pb.go
main.go
package main

import (
    "log"

    "./protos"
    "github.com/golang/protobuf/proto"
)

func main() {

    //Serialize
    test := &example.User{
        Id:   33,
        Name: "laughing_cat",
    }
    buff, err := proto.Marshal(test)
    if err != nil {
        log.Print("marshal error")
        return
    }
    log.Print("serialize success: ", buff)

    // Deserialize
    parsedTest := &example.User{}
    err = proto.Unmarshal(buff, parsedTest)

    if err != nil {
        log.Print("deserialize error: ", err)
    }
    log.Print("deserialized id :", parsedTest.Id)
    log.Print("deserialized name: ", parsedTest.Name)
}

上記で、シリアライズ=>デシリアライズ が完了するかと思います。
importの時に、*.pb.goファイルのパスを指定するのをお忘れなく。

間違えや訂正があったら教えて頂けると嬉しいですm(_ _)m。

参考

公式
今さらProtocol Buffersと、手に馴染む道具の話
Protocol BuffersでAPI通信 サーバー編【golang】 

nzer0
kadinche
弊社では 2008年の会社設立当初から、一貫して VR ソリューションの研究開発に取り組んでいます。
https://www.kadinche.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away