This project is currently in alpha. The API should be considered unstable and likely to change
protoc-gen-defaults is a protoc plugin generating the implementation of a Defaulter
interface on messages:
type Defaulter interface {
Default()
}
go get go.linka.cloud/protoc-gen-defaults
protoc-gen-defaults make use of Protobuf options to define defaults field value.
protoc-gen-defaults works the same way does the protoc plugins
Example:
protoc -I. -I defaults --go_out=paths=source_relative:. --defaults_out=paths=source_relative:. types.proto
Implementation generation can be ignored with the (defaults.ignored) = true
message option.
message NoDefaulterImplementation {
option (defaults.ignored) = true;
string string_field = 1 [(defaults.value).string = "string_field"];
}
It may be useful if you intend to write your own
Defaulter
implementation.
An empty implementation can be generated with the (defaults.disabled) = true
message option
message EmptyDefaulterImplementation {
option (defaults.disabled) = true;
string string_field = 1 [(defaults.value).string = "string_field"];
}
Each scalar or Well-Known type has its corresponding (defaults.value).[scalar] = [value]
option,
the [value]
will be set if the scalar field has the zero value, e.g 0
for numbers,
""
for strings, false
for bools
- float / google.protobuf.FloatValue:
float float = 1 [(defaults.value).float = 0.42];
- double / google.protobuf.DoubleValue:
double double = 2 [(defaults.value).double = 0.42]; ****google.protobuf.DoubleValue double_value = 20 [(defaults.value).double = 0.42];
- int32 / google.protobuf.Int32Value:
int32 int32 = 3 [(defaults.value).int32 = 42]; google.protobuf.Int32Value int32_value = 24 [(defaults.value).int32 = 42];
- int64 / google.protobuf.Int64Value:
int64 int64 = 4 [(defaults.value).int64 = 42]; google.protobuf.Int64Value int64_value = 22 [(defaults.value).int64 = 42];
- uint32 / google.protobuf.UInt32Value:
uint32 uint32 = 5 [(defaults.value).uint32 = 42]; google.protobuf.UInt32Value uint32_value = 25 [(defaults.value).uint32 = 42];
- uint64 / google.protobuf.UInt64Value:
uint64 uint64 = 6 [(defaults.value).uint64 = 42]; google.protobuf.UInt64Value uint64_value = 23 [(defaults.value).uint64 = 42];
- sint32:
sint32 sint32 = 7 [(defaults.value).sint32 = 42];
- sint64:
sint64 sint64 = 8 [(defaults.value).sint64 = 42];
- fixed32:
fixed32 fixed32 = 9 [(defaults.value).fixed32 = 42];
- fixed64:
fixed64 fixed64 = 10 [(defaults.value).fixed64 = 42];
- sfixed32:
sfixed32 sfixed32 = 11 [(defaults.value).sfixed32 = 42];
- sfixed64:
sfixed64 sfixed64 = 12 [(defaults.value).sfixed64 = 42];
- bool / google.protobuf.BoolValue:
bool bool = 13 [(defaults.value).bool = true]; google.protobuf.BoolValue bool_value = 26 [(defaults.value).bool = false];
- string / google.protobuf.StringValue:
string string = 14 [(defaults.value).string = "42"]; google.protobuf.StringValue string_value = 27 [(defaults.value).string = "42"];
- bytes / google.protobuf.BytesValue:
bytes bytes = 15 [(defaults.value).bytes = "42"]; google.protobuf.BytesValue bytes_value = 28 [(defaults.value).bytes = "42"];
Message default behaviour is defined with the (defaults.value).message = {initialize: bool, defaults: bool}
field option.
initialize
: if set totrue
the field will be initialized with an emptystuct reference
from the appropriate typedefaults
: tells that theDefault
method should be called if the type implements theDefaulter
interface
Message message = 17 [(defaults.value).message = {initialize: true, defaults: true}];
google.protobuf.Duration
The default value is parsed according to the Prometheus time durations format
google.protobuf.Duration duration = 18 [(defaults.value).duration = "2d"];
google.protobuf.Timestamp
The default value is parsed using the following RFCs as defined in the time
package:
- time.RFC822
- time.RFC822Z
- time.RFC850
- time.RFC1123
- time.RFC1123Z
- time.RFC3339
Timestamp also support a convenient value now
which will set the value from time.Now()
at Default()
method call time.
google.protobuf.Timestamp timestamp = 19 [(defaults.value).timestamp = "now"];
google.protobuf.Timestamp time_value_field_with_default = 18 [(defaults.value).timestamp = "1952-03-11T00:00:00Z"];
The enum index value if currently to zero.
enum Enum {
NONE = 0;
ONE = 1;
TWO = 2;
}
Enum enum = 16 [(defaults.value).enum = 1];
If the defaults.oneof
option is set, the oneof
will be initialized with a struct of the oneof type wrapper,
the regular field type default
option will be applied.
oneof one_of {
option (defaults.oneof) = "two";
OneOfOne one = 29 [(defaults.value).message = {defaults: true, initialize: true}];
OneOfTwo two = 30 [(defaults.value).message = {defaults: true, initialize: true}];
OneOfThree three = 31 [(defaults.value).message = {defaults: true, initialize: true}];
Enum four = 32 [(defaults.value).enum = 1];
}
repeated
and maps
are not supported.
syntax = "proto3";
package tests;
option go_package = "go.linka.cloud/protoc-gen-defaults/tests/pb;pb";
import "defaults/defaults.proto";
import "google/protobuf/wrappers.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";
message Types {
// Scalar Field Types
float float = 1 [(defaults.value).float = 0.42];
double double = 2 [(defaults.value).double = 0.42];
int32 int32 = 3 [(defaults.value).int32 = 42];
int64 int64 = 4 [(defaults.value).int64 = 42];
uint32 uint32 = 5 [(defaults.value).uint32 = 42];
uint64 uint64 = 6 [(defaults.value).uint64 = 42];
sint32 sint32 = 7 [(defaults.value).sint32 = 42];
sint64 sint64 = 8 [(defaults.value).sint64 = 42];
fixed32 fixed32 = 9 [(defaults.value).fixed32 = 42];
fixed64 fixed64 = 10 [(defaults.value).fixed64 = 42];
sfixed32 sfixed32 = 11 [(defaults.value).sfixed32 = 42];
sfixed64 sfixed64 = 12 [(defaults.value).sfixed64 = 42];
bool bool = 13 [(defaults.value).bool = true];
string string = 14 [(defaults.value).string = "42"];
bytes bytes = 15 [(defaults.value).bytes = "42"];
// Complex Field Types
enum Enum {
NONE = 0;
ONE = 1;
TWO = 2;
}
Enum enum = 16 [(defaults.value).enum = 1];
Message message = 17 [(defaults.value).message = {initialize: true, defaults: false}];
oneof one_of {
option (defaults.oneof) = "two";
OneOfOne one = 29 [(defaults.value).message = {defaults: true, initialize: true}];
OneOfTwo two = 30 [(defaults.value).message = {defaults: true, initialize: true}];
OneOfThree three = 31 [(defaults.value).message = {defaults: true, initialize: true}];
Enum four = 32 [(defaults.value).enum = 1];
}
// WellKnow types
google.protobuf.Duration duration = 18 [(defaults.value).duration = "2d"];
google.protobuf.Timestamp timestamp = 19 [(defaults.value).timestamp = "now"];
google.protobuf.DoubleValue double_value = 20 [(defaults.value).double = 0.42];
google.protobuf.FloatValue float_value = 21 [(defaults.value).float = 0.42];
google.protobuf.Int64Value int64_value = 22 [(defaults.value).int64 = 42];
google.protobuf.UInt64Value uint64_value = 23 [(defaults.value).uint64 = 42];
google.protobuf.Int32Value int32_value = 24 [(defaults.value).int32 = 42];
google.protobuf.UInt32Value uint32_value = 25 [(defaults.value).uint32 = 42];
google.protobuf.BoolValue bool_value = 26 [(defaults.value).bool = false];
google.protobuf.StringValue string_value = 27 [(defaults.value).string = "42"];
google.protobuf.BytesValue bytes_value = 28 [(defaults.value).bytes = "42"];
}
message Message {
string field = 1 [(defaults.value).string = "lonely field"];
}
message OneOfOne {
option (defaults.ignored) = true;
string string_field = 1 [(defaults.value).string = "string_field"];
}
message OneOfTwo {
string string_field = 1 [(defaults.value).string = "string_field"];
}
message OneOfThree {
option (defaults.disabled) = true;
string string_field = 1 [(defaults.value).string = "string_field"];
}
Setting protobuf message defaults is also supported using reflection:
package main
import (
pb "..."
"go.linka.cloud/protoc-gen-defaults/defaults"
)
func main() {
var msg pb.MyMessage
defaults.Apply(&msg)
}
- docs
- oneof support
- set default values by using Protobuf reflection
- add more generic methods to use as default value, e.g. uuid, bsonid... ?
- repeated support ?
- maps support ?
- bytes support