What it is
The Go implementation of Protocol Buffers — compact binary serialisation with a schema, generated types and forward and backward compatibility.
Write a .proto schema, generate Go structs, and marshal to a compact binary form. Field numbers — not names — define the wire format, which is what makes schema evolution safe.
Installation
go get google.golang.org/protobufGetting started
The smallest useful thing you can do with it, and what each part means.
go
syntax = "proto3";
package library;
option go_package = "example.com/gen/library";
message Book {
string id = 1;
string title = 2;
int32 year = 3;
repeated string tags = 4;
}Advanced usage
Where the library earns its place over a simpler alternative.
go
book := &pb.Book{Id: "42", Title: "Dune", Year: 1965}
data, err := proto.Marshal(book) // compact binary
if err != nil { return err }
var decoded pb.Book
if err := proto.Unmarshal(data, &decoded); err != nil { return err }
// An old binary reading a message with new fields simply ignores them,
// and a new binary reading an old message sees zero values.
if decoded.GetYear() == 0 {
// proto3 cannot distinguish "absent" from "zero" for scalars.
// Use optional (proto3 field presence) if that difference matters.
}Errors and fixes
The failures you are most likely to hit, and what actually resolves them.
- cannot parse invalid wire-format data
- The bytes are not protobuf, or were produced by an incompatible schema. Confirm both sides use the same field numbers.
- A nil message panics on field access
- Use the generated GetX() accessors, which return the zero value for a nil receiver.
Best practices
- Never change or reuse a field number; reserve retired ones with the `reserved` keyword.
- Use the generated getters — they are nil-safe, unlike direct field access.
- Mark fields optional when you must distinguish unset from the zero value.
- Check the schema into the repository and generate in CI so the code cannot drift from it.
Background
Why it exists, and what it was reacting to.
The google.golang.org/protobuf module is the v2 API, a full rewrite that added reflection and a cleaner separation between the wire format and generated code.
