Protocol Buffers 導入メモ Mac/Win

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

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

参考
[Protocol Buffers  |  Google Developers](https://developers.google.com/protocol-buffers/)
[Protocol Buffers - Wikipedia](https://ja.wikipedia.org/wiki/Protocol_Buffers)

# 環境
- 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)にアップグレードする](https://qiita.com/k-yamada-github/items/a748a5ea4aafdcd3cee2)

#### Win
[ここ](https://github.com/google/protobuf/releases)から、`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ファイルを作成

```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](https://developers.google.com/protocol-buffers/docs/proto3)

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

```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。

## 参考
[公式](https://developers.google.com/protocol-buffers/)
[今さらProtocol Buffersと、手に馴染む道具の話](https://qiita.com/yugui/items/160737021d25d761b353)
[Protocol BuffersでAPI通信 サーバー編【golang】　](https://qiita.com/takusemba/items/05a4431114f0c6fee3d9)