proto: generate Get methods for fields of basic type in proto3
Given proto3 schema:
message Foo {
string some_value = 1;
}
message Bar {
Foo foo = 1;
}
message Baz {
Bar bar = 1;
}
Accessing baz.bar.foo.SomeValue currently requires this code:
if f := baz.GetBar().GetFoo(); f != nil {
fmt.Printf("value was %v\n", f.SomeValue)
}
After the CL, it becomes:
fmt.Printf("value was %v\n", baz.GetBar().GetFoo().GetSomeValue())
There are downsides to generating more code:
- all things equal, less code is better
- larger API surface
The upsides are:
- consistency with proto2 API (proto2 and proto3 can be mixed. Keeping API consistent is important)
- easier to explain API - all fields have Get method. No exceptions.
- reduced user confusion - questions about this come up frequently
testing:
- added a new test
- inspected a diff for an arbitrarily chosen schema
PiperOrigin-RevId: 138212965
diff --git a/proto/proto3_test.go b/proto/proto3_test.go
index 462f805..735837f 100644
--- a/proto/proto3_test.go
+++ b/proto/proto3_test.go
@@ -93,6 +93,16 @@
}
}
+func TestGettersForBasicTypesExist(t *testing.T) {
+ var m pb.Message
+ if got := m.GetNested().GetBunny(); got != "" {
+ t.Errorf("m.GetNested().GetBunny() = %q, want empty string", got)
+ }
+ if got := m.GetNested().GetCute(); got {
+ t.Errorf("m.GetNested().GetCute() = %t, want false", got)
+ }
+}
+
func TestProto3SetDefaults(t *testing.T) {
in := &pb.Message{
Terrain: map[string]*pb.Nested{
diff --git a/protoc-gen-go/generator/generator.go b/protoc-gen-go/generator/generator.go
index 0e5d2b7..5052076 100644
--- a/protoc-gen-go/generator/generator.go
+++ b/protoc-gen-go/generator/generator.go
@@ -2076,11 +2076,6 @@
star = "*"
}
- // In proto3, only generate getters for message fields and oneof fields.
- if message.proto3() && *field.Type != descriptor.FieldDescriptorProto_TYPE_MESSAGE && !oneof {
- continue
- }
-
// Only export getter symbols for basic types,
// and for messages and enums in the same package.
// Groups are not exported.
@@ -2139,7 +2134,11 @@
continue
}
if !oneof {
- g.P("if m != nil && m." + fname + " != nil {")
+ if message.proto3() {
+ g.P("if m != nil {")
+ } else {
+ g.P("if m != nil && m." + fname + " != nil {")
+ }
g.In()
g.P("return " + star + "m." + fname)
g.Out()