{"id":225,"date":"2019-08-22T12:46:37","date_gmt":"2019-08-22T12:46:37","guid":{"rendered":"https:\/\/golangbyexamples.com\/?p=225"},"modified":"2019-11-13T15:56:59","modified_gmt":"2019-11-13T15:56:59","slug":"protocol-buffers-go","status":"publish","type":"post","link":"https:\/\/golangbyexamples.com\/protocol-buffers-go\/","title":{"rendered":"Protocol Buffers and Go: Getting started"},"content":{"rendered":"\n
In this tutorial, we will see how protocol buffers can be used in the context of GO Language.<\/p>\n\n\n\n
What is Protocol Buffer<\/strong><\/p>\n\n\n\n Protocol Buffers are data format which stores data in a structured format. Data in the protocol buffer format can be serialized and deserialized by multiple languages.<\/p>\n\n\n\n Sounds Confusing. You can think it on lines of JSON, XML but it has loads of advantages to offer. Still confusing? then don’t worry as we go along the tutorial we will understand why even a new data format is even needed.<\/p>\n\n\n\n Let’s see first with an example of the simplest protocol buffer file.<\/p>\n\n\n\n person.proto<\/strong><\/p>\n\n\n\n A couple of points to note about the above file.<\/p>\n\n\n\n Auto Generation of GO Code:<\/strong><\/p>\n\n\n\n Installations:<\/strong><\/p>\n\n\n\n After the installation is done then cd to the directory which contains the person.proto <\/strong>file. Run this command:<\/p>\n\n\n\n It will generate a data access go file with name person.pb.go <\/strong> in the same directory. <\/p>\n\n\n\n Now the biggest question is what is this person.pb.go file which has been auto-generated by protoc using person.proto . The first couple of points to notice<\/p>\n\n\n\n So basically this autogenerated file generates data accessors for Person struct and it provides methods that allow marshaling\/unmarshalling of Person struct type to\/from actual bytes. Now let’s write a main.go program to actually create concrete objects of Person<\/strong> struct. Here we will see a couple of advantages which Protocol Buffer has to offer. The below program also shows the read and write of Person struct to file.<\/p>\n\n\n\n main.go<\/strong><\/p>\n\n\n\nsyntax = \"proto3\";\n\nmessage Person {\n string name = 1;\n}<\/code><\/pre>\n\n\n\n
protoc -I .\/ --go_out=.\/ .\/person.proto<\/code><\/pre>\n\n\n\n
\/\/ Code generated by protoc-gen-go. DO NOT EDIT.\n\/\/ source: person.proto\n\n\npackage person\n\n\nimport (\n fmt \"fmt\"\n proto \"github.com\/golang\/protobuf\/proto\"\n math \"math\"\n)\n\n\n\/\/ Reference imports to suppress errors if they are not otherwise used.\nvar _ = proto.Marshal\nvar _ = fmt.Errorf\nvar _ = math.Inf\n\n\n\n\n\/\/ This is a compile-time assertion to ensure that this generated file\n\/\/ is compatible with the proto package it is being compiled against.\n\/\/ A compilation error at this line likely means your copy of the\n\/\/ proto package needs to be updated.\nconst _ = proto.ProtoPackageIsVersion3 \/\/ please upgrade the proto package\n\n\ntype Person struct {\n Name string `protobuf:\"bytes,1,opt,name=name,proto3\" json:\"name,omitempty\"`\n XXX_NoUnkeyedLiteral struct{} `json:\"-\"`\n XXX_unrecognized []byte `json:\"-\"`\n XXX_sizecache int32 `json:\"-\"`\n}\n\n\n\n\nfunc (m *Person) Reset() { *m = Person{} }\nfunc (m *Person) String() string { return proto.CompactTextString(m) }\nfunc (*Person) ProtoMessage() {}\nfunc (*Person) Descriptor() ([]byte, []int) {\n return fileDescriptor_4c9e10cf24b1156d, []int{0}\n}\n\n\nfunc (m *Person) XXX_Unmarshal(b []byte) error {\n return xxx_messageInfo_Person.Unmarshal(m, b)\n}\nfunc (m *Person) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {\n return xxx_messageInfo_Person.Marshal(b, m, deterministic)\n}\nfunc (m *Person) XXX_Merge(src proto.Message) {\n xxx_messageInfo_Person.Merge(m, src)\n}\nfunc (m *Person) XXX_Size() int {\n return xxx_messageInfo_Person.Size(m)\n}\nfunc (m *Person) XXX_DiscardUnknown() {\n xxx_messageInfo_Person.DiscardUnknown(m)\n}\n\n\nvar xxx_messageInfo_Person proto.InternalMessageInfo\n\n\nfunc (m *Person) GetName() string {\n if m != nil {\n return m.Name\n }\n return \"\"\n}\n\n\nfunc init() {\n proto.RegisterType((*Person)(nil), \"Person\")\n}\n\n\nfunc init() { proto.RegisterFile(\"person.proto\", fileDescriptor_4c9e10cf24b1156d) }\n\n\nvar fileDescriptor_4c9e10cf24b1156d = []byte{\n \/\/ 67 bytes of a gzipped FileDescriptorProto\n 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0x48, 0x2d, 0x2a,\n 0xce, 0xcf, 0xd3, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x57, 0x92, 0xe1, 0x62, 0x0b, 0x00, 0xf3, 0x85,\n 0x84, 0xb8, 0x58, 0xf2, 0x12, 0x73, 0x53, 0x25, 0x18, 0x15, 0x18, 0x35, 0x38, 0x83, 0xc0, 0xec,\n 0x24, 0x36, 0xb0, 0x22, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa4, 0xaf, 0x53, 0x72, 0x34,\n 0x00, 0x00, 0x00,\n}<\/code><\/pre>\n\n\n\n
type Person struct {\n Name string `protobuf:\"bytes,1,opt,name=name,proto3\" json:\"name,omitempty\"`\n XXX_NoUnkeyedLiteral struct{} `json:\"-\"`\n XXX_unrecognized []byte `json:\"-\"`\n XXX_sizecache int32 `json:\"-\"`\n}<\/code><\/pre>\n\n\n\n
package main\n\n\nimport (\n \"fmt\"\n \"io\/ioutil\"\n \"log\"\n proto \"github.com\/golang\/protobuf\/proto\"\n)\n\n\nfunc main() {\n person := &Person{Name: \"XXX\"}\n fmt.Printf(\"Person's name is %s\\n\", person.GetName())\n\n\n\n\n \/\/Now lets write this person object to file\n out, err := proto.Marshal(person)\n if err != nil {\n log.Fatalf(\"Serialization error: %s\", err.Error())\n }\n if err := ioutil.WriteFile(\"person.bin\", out, 0644); err != nil {\n log.Fatalf(\"Write File Error: %s \", err.Error())\n }\n fmt.Println(\"Write Success\")\n\n\n\n\n \/\/Read from file\n in, err := ioutil.ReadFile(\"person.bin\")\n if err != nil {\n log.Fatalf(\"Read File Error: %s \", err.Error())\n }\n person2 := &Person{}\n err2 := proto.Unmarshal(in, person2)\n if err2 != nil {\n log.Fatalf(\"DeSerialization error: %s\", err.Error())\n }\n\n\n fmt.Println(\"Read Success\")\n fmt.Printf(\"Person2's name is %s\\n\", person2.GetName())\n}<\/code><\/pre>\n\n\n\n