Skip to content

protoc-gen-go: support generating standard Go types in place of well-known-types #414

Open
@jhump

Description

@jhump

This is quite similar in spirit to protocolbuffers/protobuf#2055 (which is for the Java protobuf codegen and runtime).

Protos would be easier to integrate with Go libraries that rely on struct reflection (serialization, ORM, etc) if struct fields used standard Go types in place of some of the well-known types:

  • google.protobuf.Timestamp -> time.Time
  • google.protobuf.Duration -> time.Duration
  • google.protobuf.Int32Value -> *int32
  • google.protobuf.Int64Value -> *int64
  • google.protobuf.UInt32Value -> *uint32
  • google.protobuf.UInt64Value -> *uint64
  • google.protobuf.FloatValue -> *float32
  • google.protobuf.DoubleValue -> *float64
  • google.protobuf.BoolValue -> *bool
  • google.protobuf.StringValue -> *string
  • google.protobuf.BytesValue -> []byte

(For the lattermost one, we could distinguish a missing/default value from a BytesValue message that contained an empty Value field by assuming nil means absent and otherwise empty slice is a message with an empty value.)

Other solutions we've had to use to work around this (mostly the timestamp and duration ones):

  • Creating a parallel struct that mirrors the generated proto, but with the above type swaps. Implement adapter methods to translate between the proto and the parallel type. While this can be done via codegen, we find ourselves doing it by hand more often than not.
  • If the library allows customized representation (via a Marshaler or Saver sort of interface), write a reflection-based library that will recursively apply the transformations to a proto when generating the marshaled/saved form.
  • Use JSON as a go-between. The JSON format for well-known-types matches the type expectations pretty well, so marshalling the proto to JSON and then to map[string]interface{} often does the trick. Timestamps are not converted correctly, but for libraries that are applying the data to a schema, they can typically handle parsing the string, without any extra effort, for fields where a timestamp value is expected.

Since it would impact compatibility, it could be an opt-in flag that changes the output of codegen. The runtime library could probably be updated to accommodate without any compatibility issues (e.g. could just examine the type of a field to make decisions or, if it's more efficient, could encode more bits into the struct tag so that the library knows what to do without extra reflection steps).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions