📜 ⬆️ ⬇️

Go and Protocol Buffers practice (or quick start, for those who are not familiar yet)

A rather brief example is how to use Protocol Buffers in Go. It's about proto3, i.e. The 3rd version of the protocol (at the current moment alpha), a generalized example holds for the second version. There will be no description of the Protocol Buffers itself. But why pull

Training


There is no documentation for the third version, so we go here and download it. Install (everything is simple). Now as for Go, everything is here . Proper installation
go get -u github.com/golang/protobuf/{proto,protoc-gen-go} 
You may need -f if you specify in ~/.gitconfig
 [url "ssh://git@github.com/"] insteadOf = https://github.com/ 
If you are not familiar with Protocl Buffers, then here ( English ) description of the 2nd version. For the third version, while there is no documentation, it remains to be content only with this .

Example


For example, we will save an array of numbers and a string, and then read them back. Further we will consider that we are at the root of our new project. The proto-file will look like this.
msg / msg.proto
 //    C/C++ /*    */ //   3,     -     syntax = "proto3"; //  ,   go-   package msg; //  ,     message Msg { //  _ = _ string key = 1; // repeated  slice repeated int64 value = 2; } /*     required   extensions  extensions  (  )  Any    */ //   Sublime    

Now you need to compile the proto-file.
  protoc --go_out=. msg/*.proto 

As a result, we get such a file
msg / msg.pb.go
 //   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() { } 

Now create a structure, write its bytes, and read it back.
main.go
 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") } 

As you can see, “it's easier than steamed turnip” If you dig deeper, let's say there is a desire to create some kind of database that stores “messages” - so that the type of “messages” is not initially defined, and to keep these “messages” in the membership of a certain structure. In other words, to have a library that will preserve what we give it in a certain format. In proto3, the third version of protocol buffers, the Any type is implemented to store any types. So says the release note, but in fact so far so . Will have to wait. However, if you look at the option under the link above, then the principle becomes clear - it's up to implementation. Any looks like this:
 message Any { string type_url = 1; //  bytes value = 2; //     } 

Which means ... But for a long time to tell, take a look at an example . In essence, this is the registration of all types used and double marshaling - marshaling of some type, and then marshaling the basic structure. All this is wildly peppered with reflection. Yes - reflection is a long time, there's nothing you can do. That's all.
Reference

Protocol Buffers Releases on github
Ibid, tracker
One of the implementations of Protocol Buffers for Go
Protocol Buffers Guide v2
Ibid, basic data types

Update



')

Source: https://habr.com/ru/post/252455/


All Articles