Skip to content

cmd/protoc-gen-go-grpc: Add flag to use separate service package #8280

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

qianlongzt
Copy link

@qianlongzt qianlongzt commented Apr 30, 2025

Fixes: #8233

Release notes for cmd/protoc-gen-go-grpc:

  • A new boolean flag named use_separate_service_package has been added to support generating service and message code in separate packages. When this flag is set to true, the service code will import the message package and refer to message symbols using package-qualified names. Since both the service and message code still share the same package names, users must either use the --go-grpc_out flag to place the service code in a different directory or manually move it.

RELEASE NOTES: none

@arjan-bal arjan-bal self-requested a review April 30, 2025 18:26
@arjan-bal arjan-bal self-assigned this Apr 30, 2025
@arjan-bal arjan-bal added this to the 1.73 Release milestone Apr 30, 2025
@arjan-bal arjan-bal added the Type: Feature New features or improvements in behavior label Apr 30, 2025
Copy link

codecov bot commented Apr 30, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 82.19%. Comparing base (080f956) to head (a79e9fb).
Report is 31 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #8280      +/-   ##
==========================================
+ Coverage   82.13%   82.19%   +0.06%     
==========================================
  Files         417      417              
  Lines       41385    41385              
==========================================
+ Hits        33991    34018      +27     
+ Misses       5961     5941      -20     
+ Partials     1433     1426       -7     

see 15 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@arjan-bal arjan-bal assigned qianlongzt and unassigned arjan-bal Apr 30, 2025
@arjan-bal arjan-bal changed the title feat(cmd/gen): add flag use_separate_service_package cmd/protoc-gen-go-grpc: Add flag to use separate service package Apr 30, 2025
@@ -58,6 +61,7 @@ func main() {
var flags flag.FlagSet
requireUnimplemented = flags.Bool("require_unimplemented_servers", true, "set to false to match legacy behavior")
useGenericStreams = flags.Bool("use_generic_streams_experimental", true, "set to true to use generic types for streaming client and server objects; this flag is EXPERIMENTAL and may be changed or removed in a future release")
useSeparateServicePackage = flags.Bool("use_separate_service_package", false, "set to true to use separate service package, service package will import protobuf package")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about something like: name this output_package and make it a string? Then the import path could be file.GoImportPath with everything after the last / stripped and replaced by what's specified here? That would allow more flexibility for how the code is generated.

Copy link
Author

@qianlongzt qianlongzt May 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import path becomes unnecessary after the file is generated.

#8245.
#8233 (comment)

Copy link
Contributor

@arjan-bal arjan-bal May 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The package name can't be changed by the gRPC plugin, it is controlled by the Go protobuf compiler. It is usually specified by the go_package option in the .proto file, but there are other ways also (see docs).

Users can place the _grpc.pb.go file in a separate directory by using the different values for --go_out and --go_grpc_out flags. The semantics of the --go_grpc_out flag are the same as --go_out described here. For example, calling the following command:

❯ protoc --go-grpc_opt="use_separate_service_package=true,module=google.golang.org/grpc" --go-grpc_out="service" \
    --go_opt="module=google.golang.org/grpc", --go_out=. "examples/route_guide/routeguide/route_guide.proto"  

will produce the files in the following directories:

examples/route_guide/routeguide/
├── route_guide.pb.go
service/
└── examples/route_guide/routeguide/
    └── route_guide_grpc.pb.go

This means that you can specify a custom path prefix for the generated code. This doesn't help in cases where you want to add a path suffix, e.g: if you want to place oute_guide_grpc.pb.go in examples/route_guide/routeguide/service/ in the example above. For such cases, users can copy the generated code, though it is suboptimal.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the most user friendly solution to split package would be to have a proto option like go_grpc_package which has semantics similar to go_package. The probuf complier would then need to handle splitting the service and message code when go_package and go_grpc_package are different.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that something we can do? I thought the options were defined by protobuf. We could propose a go_services_package if so. The Go protobuf team seems to prefer this ideology anyway (generate services and messages into separate packages).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible to change the package name in the generated gRPC service file by setting file.GoPackageName += protogen.GoPackageName(packageSuffix). I found this in connectrpc's codegen.

if packageSuffix != "" {
    if !token.IsIdentifier(packageSuffix) {
        plugin.Error(fmt.Errorf("package_suffix %q is not a valid Go identifier", packageSuffix))
        return
    }
    file.GoPackageName += protogen.GoPackageName(packageSuffix)
    generatedFilenamePrefixToSlash := filepath.ToSlash(file.GeneratedFilenamePrefix)
    file.GeneratedFilenamePrefix = path.Join(
        path.Dir(generatedFilenamePrefixToSlash),
        string(file.GoPackageName),
        path.Base(generatedFilenamePrefixToSlash),
    )
    goImportPath = protogen.GoImportPath(path.Join(
        string(file.GoImportPath),
        string(file.GoPackageName),
    ))
}

With this, we can allow the user to configure a suffix. The grpc code will be placed in a subdirectory with name package_<suffix> and with a package name package_<suffix>.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be my preference, then.

We should think about whether renaming the package completely would be better than just adding a suffix. I'm not sure which one would be better, but either would be better than the previous proposal.

@qianlongzt qianlongzt force-pushed the feat-use-separate-service-package branch from 62d01f8 to a79e9fb Compare May 2, 2025 07:06
@dfawley dfawley removed their assignment May 9, 2025
Copy link

This PR is labeled as requiring an update from the reporter, and no update has been received after 6 days. If no update is provided in the next 7 days, this issue will be automatically closed.

@github-actions github-actions bot added the stale label May 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

protoc-gen-go-grpc support split single proto file gen to diffrent package
3 participants