Working with Well-Known Types
1. Using Timestamp Type
Example: Timestamp in a message
import "google/protobuf/timestamp.proto";
message Event {
string id = 1;
google.protobuf.Timestamp occurred_at = 2;
}
| Property | Detail |
|---|---|
| Fields | seconds (int64) + nanos (int32) |
| Range | 0001-01-01 to 9999-12-31 (UTC) |
| JSON | RFC 3339 string e.g. "2026-05-18T10:00:00Z" |
| Go helper | timestamppb.Now() / .AsTime() |
2. Using Duration Type
| Property | Detail |
|---|---|
| Import | google/protobuf/duration.proto |
| Fields | seconds + nanos (signed) |
| JSON | "3.5s" |
| Go helper | durationpb.New(time.Second) |
3. Using Any Type
Example: Packing/unpacking Any
import "google.golang.org/protobuf/types/known/anypb"
a, _ := anypb.New(&User{Id: "u1"})
var u User
_ = a.UnmarshalTo(&u)
| Field | Purpose |
|---|---|
type_url | Fully-qualified type URL (type.googleapis.com/pkg.Name) |
value | Serialized message bytes |
4. Using Struct Type
| Field | Detail |
|---|---|
fields | map<string, Value> — arbitrary JSON-like data |
| Use case | Schema-less payload, dynamic config |
| JSON | Native JSON object |
5. Using Empty Type
Example: RPC with no input or output
import "google/protobuf/empty.proto";
service Health {
rpc Ping(google.protobuf.Empty) returns (google.protobuf.Empty);
}
| Note | Detail |
|---|---|
| Future-proof alt | Use a dedicated PingRequest{} so you can add fields later |
6. Using FieldMask Type
Example: Partial update with FieldMask
import "google/protobuf/field_mask.proto";
message UpdateUserRequest {
User user = 1;
google.protobuf.FieldMask update_mask = 2; // e.g. paths="email,profile.name"
}
| Field | Purpose |
|---|---|
paths | List of field paths to update |
| Convention | Update only listed paths; ignore others |
7. Using Wrapper Types
| Wrapper | Wraps | Purpose |
|---|---|---|
| StringValue / BytesValue | string / bytes | Presence tracking |
| Int32/64Value, UInt32/64Value | integers | Distinguish 0 from unset |
| FloatValue / DoubleValue | float / double | Distinguish 0.0 from unset |
| BoolValue | bool | Distinguish false from unset |
Note: Prefer
optional over wrappers in proto3 — wrappers exist for legacy and JSON interop.8. Importing Well-Known Types
| Import Path | Provides |
|---|---|
google/protobuf/timestamp.proto | Timestamp |
google/protobuf/duration.proto | Duration |
google/protobuf/any.proto | Any |
google/protobuf/struct.proto | Struct, Value, ListValue |
google/protobuf/empty.proto | Empty |
google/protobuf/field_mask.proto | FieldMask |
google/protobuf/wrappers.proto | *Value wrappers |
9. Converting Between Native and Proto Types
| Native (Go) | Proto | Conversion |
|---|---|---|
time.Time | Timestamp | timestamppb.New(t) / ts.AsTime() |
time.Duration | Duration | durationpb.New(d) / d.AsDuration() |
map[string]any | Struct | structpb.NewStruct(m) |
10. Using Value Type
| Variant (oneof) | Maps To |
|---|---|
null_value | null |
number_value | double |
string_value | string |
bool_value | bool |
struct_value | Struct |
list_value | ListValue |