0%

protocol buffer & go 예제

원문

기본 https://developers.google.com/protocol-buffers
문법 https://developers.google.com/protocol-buffers/docs/proto3
go 튜토리얼 https://developers.google.com/protocol-buffers/docs/gotutorial

protocol buffer 란

구글에서 개발하고 오픈소스로 공개한 직렬화된 데이터 구조입니다.

다음과 같은 특징을 갖습니다.

  • C++, c#, java, python, object c, javascript, php, go 등 다양한 언어를 지원합니다.
  • 직렬화 속도가 빠르며, 용량이 적습니다.
  • 직렬화 데이터를 파싱할 필요가 없습니다. 데이터를 객체를 그대로 사용 할 수 있습니다.
  • proto 문법 학습이 필요합니다.
  • gRPC 에서도 메시지 전달 방식을 protocol buffer 로 사용하고 있어 숙지한다면 gRPC도 쉽게 접근이 가능합니다.

직렬화: 파일을 바이너리 스트림 형태로 저장하는 행위

구성 및 사용

  1. proto 문법으로 데이터 포맷을 작성합니다.
  2. protoc 를 통해 원하는 프로그래밍 언어 형식의 데이터 파일을 생산합니다.
  3. 개발하고자 하는 언어에서 제공되는 protocol buffer API 를 사용한다.

protoc 컴파일러 설치

컴파일러와 언어별 SDK 를 아래 사이트에서 다운받을 수 있습니다.
https://github.com/protocolbuffers/protobuf/releases

protoc-3.11.4-win64.zip

cmd 또는 bash 에서 protoc 를 인식할 수 있도록 환경변수를 셋팅해야합니다.

1
2
$ protoc --version
libprotoc 3.11.4

.proto 파일 작성

protocl buffer syntax 3 보기

go 를 활용한 예제

.proto 파일 작성

/unit/pencil.proto

1
2
3
4
5
6
7
syntax = "proto3";
package unit;

message Pencil {
string color = 1;
int32 price = 2;
}

protoc-gen-go 의존성 설치

go 에서는 .proto 파일을 protoc 하기위해 별도 의존성을 따로 제공하고 있습니다.

1
$ go install google.golang.org/protobuf/cmd/protoc-gen-go

protoc 로 컴파일

1
2
$ cd unit
$ protoc -I . pencil.proto --go_out=.

컴파일 이후 아래 /unit/pancil.pb.go 파일이 생성된것을 확인할 수 있습니다.

go 직렬화 & 역직렬화

mod init

1
$ go mod init protocol_buffer

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package main

import (
"github.com/golang/protobuf/proto" // proto api 의존성
"io/ioutil"
"log"
pb "protocol_buffer/unit"
)

const (
filename = "pencil"
)

func main() {
// 쓰기
writeMessage()
// 읽기
readMessage()
}

func writeMessage() {
pencil := &pb.Pencil{Color:"red", Price:1200}

// proto 의존성을 통해 인코딩
out, err := proto.Marshal(pencil)
if err != nil {
log.Fatalf("Failed to encode Pencil: %v", err)
}

if err := ioutil.WriteFile(filename, out, 0644); err != nil {
log.Fatalf("Failed to write Pencil: %v", err)
}
}

func readMessage() {
in, err := ioutil.ReadFile(filename)
if err != nil {
log.Fatalln("Error reading file:", err)
}

pencil := &pb.Pencil{}

// proto 의존성을 통해 디코딩
if err := proto.Unmarshal(in, pencil); err != nil {
log.Fatalln("Failed to parse pencil:", err)
}

log.Printf("color: %s", pencil.GetColor())
log.Printf("price: %d", pencil.GetPrice())
}

Run & Result

1
2
3
$ go run main.go
2020/03/19 16:54:57 color: red
2020/03/19 16:54:57 price: 1200

직렬화된 파일

/pencil

1
2

red�

사람이 읽을 수 없도록 인코딩 되어있습니다.