- PVSM.RU - https://www.pvsm.ru -
Весьма короткий пример как использовать Protocol Buffers в Go. Речь пойдёт о proto3, т.е. 3-ей версии протокола (на текущим момент альфа), обобщённо пример справедлив и для второй версии. Не будет описания самого Protocol Buffers. Впрочем чего тянуть
Документации по третьей версии нет, поэтому идём сюда [1] читаем и качаем. Устанавливаем (там всё просто). Теперь что касается Go — всё здесь [2]. Собственно установка
go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
Может понадобиться -f если в ~/.gitconfig у Вас указано
[url "ssh://git@github.com/"]
insteadOf = https://github.com/
Если Вы ещё не знакомы с Protocl Buffers, то здесь [3] (англ.) описание 2-ой версии. Для третьей версии пока нет документации, остаётся довольствоваться лишь этим [1].
Для примера будем сохранять массив из чисел и строку, а потом читать их обратно. Далее будем считать что мы находимся в корне нашего нового проекта. Прото-файл будет выглядеть так
// комментарии как в C/C++
/*
и многострочные тоже
*/
// синтаксис версии 3, она пока что альфа - будем думать о будующем
syntax = "proto3";
// имя пакета, в результирующем go-файле это сохраниться
package msg;
// тип данных, которые мы будем сохранять
message Msg {
// тип имя_поля = номер_поля
string key = 1;
// repeated означает slice
repeated int64 value = 2;
}
/*
в третьей версии нет required полей и extensions
вместо extensions реализован (пока ещё не) тип Any о нём попозже
*/
// кстати для Sublime есть подсветка синтаксиса
Теперь необходимо скомпилировать прото-файл
protoc --go_out=. msg/*.proto
В результате получим такой во файлик
// комментарии выпилены
package msg
import proto "github.com/golang/protobuf/proto"
var _ = proto.Marshal
/*
Структура обрела такой вид. Обратите внимание, что автоматически добавлены тэги для JSON
*/
type Msg struct {
Key string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"`
Value []int64 `protobuf:"varint,2,rep,name=value" json:"value,omitempty"`
}
// методы необходимы, чтобы структура соответствовала интерфейсу proto.Message
func (m *Msg) Reset() { *m = Msg{} }
func (m *Msg) String() string { return proto.CompactTextString(m) }
func (*Msg) ProtoMessage() {}
func init() {
}
Теперь создадим структуру, запишем её байты, и прочитаем обратно
package main
import (
"log"
"./msg"
"github.com/golang/protobuf/proto"
)
func main() {
// создадим новое "сообщение"
msg1 := &msg.Msg{
Key: "Hello Protocol Buffers",
Value: []int64{1, 2, 3, 4},
}
// структуру в байты
data, err := proto.Marshal(msg1)
if err != nil {
log.Fatal("marshaling error: ", err)
return
}
// сколько же она занимает памяти?
log.Printf("data length: %d", len(data))
// байты в структуру
msg2 := new(msg.Msg)
err = proto.Unmarshal(data, msg2)
if err != nil {
log.Fatal("unmarshaling error: ", err)
}
// теперь обе структкры должны быть равны
if msg1.Key != msg2.Key {
log.Printf("unexpected value, expected '%s', got '%s'", msg1.Key, msg2.Key)
}
for i := 0; i < 4; i++ {
if msg1.Value[i] != msg2.Value[i] {
log.Printf("unexpected value, expected %d, got %d", msg1.Value[i], msg2.Value[i])
}
}
log.Println("Done")
}
Как видите «проще пареной репы». Если копнуть глубже, допустим есть желание создать некую базу, хранящую «сообщения» — так, что тип «сообщения» изначально не определён, причём сохранять эти «сообщения» в членстве некой структуры. Иными словами иметь библиотеку, которая будет сохранять то, что мы ей дадим в определённом формате. В proto3 — третьей версии protocol buffers — реализован тип Any, для хранения любых типов. Так гласит заметка к релизу, а на деле пока что так [4]. Придётся подождать. Однако если взглянуть на вариант по ссылке выше, то принцип становиться ясен — дело за реализацией. Any выглядит так:
message Any {
string type_url = 1; // тип
bytes value = 2; // содержимое типа в байтах
}
Что означает… Впрочем долго рассказывать, взгляните на пример [5]. По сути это регистрация всех используемых типов и двойной маршалинг — маршалинг некоего типа, а затем маршалинг базовой структуры. Всё это дико поперчёно рефлексией. Да — рефлексия это долго, тут ничего не поделаешь. На этом всё.
Релизы Protocol Buffers на GitHub [1]
Там же, трекер [6]
Одна из реализаций Protocol Buffers для Go [2]
Путеводитель по Protocol Buffers v2 [3]
Там же, базовые типы данных [7]
Автор: deep_orange
Источник [8]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/hranenie-danny-h/85320
Ссылки в тексте:
[1] сюда: https://github.com/google/protobuf/releases
[2] здесь: https://github.com/golang/protobuf
[3] здесь: https://developers.google.com/protocol-buffers/docs/proto
[4] так: https://github.com/google/protobuf/issues/198
[5] пример: https://github.com/logrusorgru/gopb3any
[6] Там же, трекер: https://github.com/google/protobuf/issues
[7] Там же, базовые типы данных: https://developers.google.com/protocol-buffers/docs/proto#scalar
[8] Источник: http://habrahabr.ru/post/252455/
Нажмите здесь для печати.