I've got the following
message Value {
enum Strategy {
STRATEGY_1 = 1;
STRATEGY_2 = 2;
}
Strategy strategy = 1;
}
I need to reuse that enum now so I want to refactor it to
enum Strategy {
STRATEGY_1 = 1;
STRATEGY_2 = 2;
}
message Value {
Strategy strategy = 1;
}
Is this a breaking change protocol wise or not?
It's not a breaking change protocol wise.
This can be verified by comparing the proto serialized data for each case.
v1.proto
syntax = "proto3";
package v1;
option go_package = "github.com/stackoverflow/pbtest/gen/v1";
message Value {
enum Strategy {
STRATEGY_0 = 0;
STRATEGY_1 = 1;
STRATEGY_2 = 2;
}
Strategy strategy = 1;
}
v2.proto
syntax = "proto3";
package v2;
option go_package = "github.com/stackoverflow/pbtest/gen/v2";
enum Strategy {
STRATEGY_0 = 0;
STRATEGY_1 = 1;
STRATEGY_2 = 2;
}
message Value {
Strategy strategy = 1;
}
Setup a Go module and generate code from the protobuf definitions:
$ go mod init github.com/stackoverflow/pbtest
go: creating new go.mod: module github.com/stackoverflow/pbtest
go: to add module requirements and sums:
go mod tidy
$ protoc --go_out=. --go_opt=module=github.com/stackoverflow/pbtest v1.proto
$ protoc --go_out=. --go_opt=module=github.com/stackoverflow/pbtest v2.proto
$ go mod tidy
go: finding module for package google.golang.org/protobuf/runtime/protoimpl
go: finding module for package google.golang.org/protobuf/reflect/protoreflect
go: found google.golang.org/protobuf/reflect/protoreflect in google.golang.org/protobuf v1.30.0
go: found google.golang.org/protobuf/runtime/protoimpl in google.golang.org/protobuf v1.30.0
Then write some code that marshals each version
main.go
package main
import (
"bytes"
"fmt"
"google.golang.org/protobuf/proto"
v1 "github.com/stackoverflow/pbtest/gen/v1"
v2 "github.com/stackoverflow/pbtest/gen/v2"
)
func main() {
v1pb, err := proto.Marshal(&v1.Value{
Strategy: v1.Value_STRATEGY_1,
})
if err != nil {
panic(err)
}
v2pb, err := proto.Marshal(&v2.Value{
Strategy: v2.Strategy_STRATEGY_1,
})
if err != nil {
panic(err)
}
fmt.Printf("v1: %x\n", v1pb)
fmt.Printf("v2: %x\n", v2pb)
fmt.Printf("equal: %t\n", bytes.Equal(v1pb, v2pb))
}
..and run it:
$ go run .
v1: 0801
v2: 0801
equal: true
As you can see, the values are identical.
Small aside
You mention you want to re-use the enum - it's perhaps not too well know, but you can still do that when an enum is defined within another message definition. You simply need to qualify the reference with the message name. For example:
message AnotherValue {
Value.Strategy strategy = 1;
}
That said, it's often going to be cleaner to simply extract the enum definition out.