I have an issue, where two projects need to use the same .pb.go file and this obviously generates the "duplicate type registered" error, if one of the projects imports the other project.
The layout for the projects:
-proto-project
-- service.proto
-service-project
-| cmd
--- service.go
-| generated
--- service.pb.go
-other-project
-| cmd
--- other.go
-| generated
--- service.pb.go
Obviously, this could be solved by generating the .pb.go inside proto-project, but then there would be some manual versioning needed, if different projects need different version.
Any thoughts?
Ideally, the service.proto as well as the service.pb.go should reside in a common import path for both projects. You should avoid generating a .pb.go and then copying it whole into another codebase to make use of it there.
Protofiles are shared and used by both project, we have problem in git submodule, because we connect protofiles like git submodule. And problem exist when submodule used protofiles too, like main project, in that case we have naming conflict.
@puellanivis yes, I realize, this, but we need to have different versions of .pb.go for different projects. So the layout is actually more similar to this:
-proto-project
-| v3
--- servicev3.proto
-service-project
-| cmd
--- service.go
-| generated
--- servicev2.pb.go
-other-project
-| cmd
--- other.go
-| generated
--- servicev1.pb.go
-other-project2
-| cmd
--- other2.go
-| generated
--- servicev2.pb.go
-other-project3
-| cmd
--- other3.go
-| generated
--- servicev3.pb.go
First workaround
One way to solve this is to remove the init functions from the .pb.go to avoid collision, but it's bit ad hoc
sed '0,/init/{s/init/initNotCalled/}' generated/service.pb.go > /tmp/tmp.$$
cat /tmp/tmp.$$ > generated/service.pb.go
rm -f /tmp/tmp.$$
Second workaround
Use different package name during generation
Third workaround
Pass function as a parameter to service-project to call the .pb.go inside other-project, so that service-project has no .pb.go dependencies
Obviously, this could be solved by generating the .pb.go inside proto-project
This is highly recommended.
we need to have different versions of .pb.go for different projects
I'm not sure what this means. Using semver definitions, are these major versions or minor versions?
"my.company.prefix.service.v2").First workaround
One way to solve this is to remove the init functions from the .pb.go to avoid collision, but it's bit ad hoc
This is going to run into issues later on as the protobuf language requires the use of registration for dynamic usages like Any and extensions. Even worse, the failures will be more obscure. Loud up-front failure is better than quiet and subtle failures later on.
Second workaround
Use different package name during generation
Are you talking about the proto package or the Go package? Depending on which, both could work:
.pb.go file, which all project then import.Third workaround
Pass function as a parameter toservice-projectto call the .pb.go insideother-project, so thatservice-projecthas no .pb.go dependencies
I'm not sure what this means. Are you suggesting a form of dependency injection? I guess that might work, but it's a roundabout way to avoid the problem.
As an example of .proto and .pb.go file management, there's the approach that the Google Cloud APIs take:
.proto files are located in one repository:.pb.go files are located in another repository:In these you see examples of what I said earlier:
.proto file specifies exactly what the canonical Go import path is for that file.go-genproto repository versions the set of all generated .pb.go as a large monolithic Go module. If you wanted finer granularity, you could have each sub-directory to contain its own go.mod file. Thus, you could version each directory separately from another.I'm going to close this. If you have addition questions, I can try and help, but global uniqueness in the protobuf namespace is absolute requirement for the proper functioning of protobufs.
I have also a similar issue. I have some messages and methods which are in common proto.
message Some {
some Int
}
service-1 and service-2 are importing the common.proto like import "common.proto";
-service-1-go-package
-| cmd
--- service-1-proto which includes common.proto
-service-2-go-package
-| cmd
--- service-2-proto which includes common.proto
While using generated pb.go files of these services files, I am getting
a message which says - proto: duplicate proto type registered: common.Some
I know it's registering the common.Some two times. But can I ignore registering the same message multiple times? Could you please suggest to me something helpful?
Most helpful comment
As an example of
.protoand.pb.gofile management, there's the approach that the Google Cloud APIs take:.protofiles are located in one repository:.pb.gofiles are located in another repository:In these you see examples of what I said earlier:
.protofile specifies exactly what the canonical Go import path is for that file.go-genprotorepository versions the set of all generated.pb.goas a large monolithic Go module. If you wanted finer granularity, you could have each sub-directory to contain its owngo.modfile. Thus, you could version each directory separately from another.