Skip to content

protobuf

E. Lynette Rayle edited this page Jul 11, 2023 · 1 revision

intro video

Reference: Google protocol-buffers

Data comparison

xml (49b)

<xml>
  <name>Elliot</name>
  <age>24</age>
<xml>

json (35b)

{
  "Name": "Elliot",
  "Age": 24
}

proto (10b)

[10 6 69 108 108 105 111 116 16 24]

I'm guessing that each number is stored as a single byte.

This is my intuitive assumptions about what's going on.

  • 10 - identifies the ID of the struct
  • 6 - identifies the Name field
  • 69 108 108 105 111 116 - encodes "Elliot"
  • 16 - identifies the Age field
  • 24 - encodes 24

Can encode numbers < 255 as a single byte. Can encode latin alpha-num as a single byte.

How to use

load required packages

> go get github.com/golang/protobuf
> go get github.com/golang/protobuf/proto
> protoc

Last command should show help info for protoc. Video says to "export the path to ensure that proto C binary is available from terminal". Not sure how to do that. (2:56)

defining a 'message' which is the data structure

# File: person.proto

syntax="proto3"

package main;

message Person {
  string name = 1;
  int32 age = 2;
}

generate code from proto def

in terminal

> protoc --go_out=. *.proto
  • generates person.pb.go with Person struct and basic functions (Reset, String, ProtoMessage, Descriptor, XXX_Unmarshal, XXX_Marshal, etc.)

using resulting generated code

# main.go

package main

import "fmt"

type Person struct {
  Name string
  Age  int
}

func main() {
  elliot := &Person{
    Name: "Elliot",
    Age: 24,
  }

  # convert elliot to proto data
  data, err := proto.Marshal(elliot)
  if err != nil {
    log.Fatal("Marshalling error: ", err)
  }

  fmt.Println(data) # [10 6 69 108 108 105 111 116 16 24]

  # convert proto data back to Person
  newElliot := &Person{} # setup outgoing receiving param

  # RPC call where data is incoming and newElliot is outgoing
  err = proto.Unmarshal(data, newElliot)
  if err != nil {
    log.Fatal("Unmarshalling error: ", err)
  }
  
  fmt.Println(newElliot.GetName()) # "Elliot"}
  fmt.Println(newElliot.GetAge())  # 24}
}

run in terminal

> go run main.go person.pb.go