Service Group

Overview

go-zero uses gRPC to communicate between services. We define the interface of the service with proto files, but we may have multiple services in physical development. If the service is not clustered, the goctl generated code will be a large folder, leading to poor maintenance variability, so that the service group can improve the readability and maintenance of the code.

Service Group

In go-zero, by clustering files using service as a dimension in the proto file. We can define multiple services in the proto file and create a separate folder for each service so that different services can be grouped in order to improve readability and maintenance.

In addition to service defined in proto file, groups need to be controlled in goctl, creating code with or without groups depends on developers. We show it by example.

No group

Assume we have a proto file, below:

  1. syntax = "proto3";
  2. package user;
  3. option go_package = "github.com/example/user";
  4. message LoginReq{}
  5. message LoginResp{}
  6. message UserInfoReq{}
  7. message UserInfoResp{}
  8. message UserInfoUpdateReq{}
  9. message UserInfoUpdateResp{}
  10. message UserListReq{}
  11. message UserListResp{}
  12. message UserRoleListReq{}
  13. message UserRoleListResp{}
  14. message UserRoleUpdateReq{}
  15. message UserRoleUpdateResp{}
  16. message UserRoleInfoReq{}
  17. message UserRoleInfoResp{}
  18. message UserRoleAddReq{}
  19. message UserRoleAddResp{}
  20. message UserRoleDeleteReq{}
  21. message UserRoleDeleteResp{}
  22. message UserClassListReq{}
  23. message UserClassListResp{}
  24. message UserClassUpdateReq{}
  25. message UserClassUpdateResp{}
  26. message UserClassInfoReq{}
  27. message UserClassInfoResp{}
  28. message UserClassAddReq{}
  29. message UserClassAddResp{}
  30. message UserClassDeleteReq{}
  31. message UserClassDeleteResp{}
  32. service UserService{
  33. rpc Login (LoginReq) returns (LoginResp);
  34. rpc UserInfo (UserInfoReq) returns (UserInfoResp);
  35. rpc UserInfoUpdate (UserInfoUpdateReq) returns (UserInfoUpdateResp);
  36. rpc UserList (UserListReq) returns (UserListResp);
  37. rpc UserRoleList (UserRoleListReq) returns (UserRoleListResp);
  38. rpc UserRoleUpdate (UserRoleUpdateReq) returns (UserRoleUpdateResp);
  39. rpc UserRoleInfo (UserRoleInfoReq) returns (UserRoleInfoResp);
  40. rpc UserRoleAdd (UserRoleAddReq) returns (UserRoleAddResp);
  41. rpc UserRoleDelete (UserRoleDeleteReq) returns (UserRoleDeleteResp);
  42. rpc UserClassList (UserClassListReq) returns (UserClassListResp);
  43. rpc UserClassUpdate (UserClassUpdateReq) returns (UserClassUpdateResp);
  44. rpc UserClassInfo (UserClassInfoReq) returns (UserClassInfoResp);
  45. rpc UserClassAdd (UserClassAddReq) returns (UserClassAddResp);
  46. rpc UserClassDelete (UserClassDeleteReq) returns (UserClassDeleteResp);
  47. }

Let’s look at the structure of the code generated by goctl without grouping:

  1. $ goctl rpc protoc user.proto --go_out=. --go-grpc_out=. --zrpc_out=.
  2. $ tree
  3. .
  4. ├── etc
  5. └── user.yaml
  6. ├── github.com
  7. └── example
  8. └── user
  9. ├── user.pb.go
  10. └── user_grpc.pb.go
  11. ├── go.mod
  12. ├── internal
  13. ├── config
  14. └── config.go
  15. ├── logic
  16. ├── loginlogic.go
  17. ├── userclassaddlogic.go
  18. ├── userclassdeletelogic.go
  19. ├── userclassinfologic.go
  20. ├── userclasslistlogic.go
  21. ├── userclassupdatelogic.go
  22. ├── userinfologic.go
  23. ├── userinfoupdatelogic.go
  24. ├── userlistlogic.go
  25. ├── userroleaddlogic.go
  26. ├── userroledeletelogic.go
  27. ├── userroleinfologic.go
  28. ├── userrolelistlogic.go
  29. └── userroleupdatelogic.go
  30. ├── server
  31. └── userserviceserver.go
  32. └── svc
  33. └── servicecontext.go
  34. ├── user.go
  35. ├── user.proto
  36. └── userservice
  37. └── userservice.go
  38. 10 directories, 24 files
Service Group - 图1reminding

does not support the definition of multiple services in proto file without being grouped or reporting errors.

Group

First, we need to define multiple services in proto file, as follows::

  1. syntax = "proto3";
  2. package user;
  3. option go_package = "github.com/example/user";
  4. message LoginReq{}
  5. message LoginResp{}
  6. message UserInfoReq{}
  7. message UserInfoResp{}
  8. message UserInfoUpdateReq{}
  9. message UserInfoUpdateResp{}
  10. message UserListReq{}
  11. message UserListResp{}
  12. service UserService{
  13. rpc Login (LoginReq) returns (LoginResp);
  14. rpc UserInfo (UserInfoReq) returns (UserInfoResp);
  15. rpc UserInfoUpdate (UserInfoUpdateReq) returns (UserInfoUpdateResp);
  16. rpc UserList (UserListReq) returns (UserListResp);
  17. }
  18. message UserRoleListReq{}
  19. message UserRoleListResp{}
  20. message UserRoleUpdateReq{}
  21. message UserRoleUpdateResp{}
  22. message UserRoleInfoReq{}
  23. message UserRoleInfoResp{}
  24. message UserRoleAddReq{}
  25. message UserRoleAddResp{}
  26. message UserRoleDeleteReq{}
  27. message UserRoleDeleteResp{}
  28. service UserRoleService{
  29. rpc UserRoleList (UserRoleListReq) returns (UserRoleListResp);
  30. rpc UserRoleUpdate (UserRoleUpdateReq) returns (UserRoleUpdateResp);
  31. rpc UserRoleInfo (UserRoleInfoReq) returns (UserRoleInfoResp);
  32. rpc UserRoleAdd (UserRoleAddReq) returns (UserRoleAddResp);
  33. rpc UserRoleDelete (UserRoleDeleteReq) returns (UserRoleDeleteResp);
  34. }
  35. message UserClassListReq{}
  36. message UserClassListResp{}
  37. message UserClassUpdateReq{}
  38. message UserClassUpdateResp{}
  39. message UserClassInfoReq{}
  40. message UserClassInfoResp{}
  41. message UserClassAddReq{}
  42. message UserClassAddResp{}
  43. message UserClassDeleteReq{}
  44. message UserClassDeleteResp{}
  45. service UserClassService{
  46. rpc UserClassList (UserClassListReq) returns (UserClassListResp);
  47. rpc UserClassUpdate (UserClassUpdateReq) returns (UserClassUpdateResp);
  48. rpc UserClassInfo (UserClassInfoReq) returns (UserClassInfoResp);
  49. rpc UserClassAdd (UserClassAddReq) returns (UserClassAddResp);
  50. rpc UserClassDelete (UserClassDeleteReq) returns (UserClassDeleteResp);
  51. }

Let’s look at the structure of the code generated by goctl with grouping:

  1. # 通过 -m 指定 goctl 生成分组的代码
  2. $ goctl rpc protoc user.proto --go_out=. --go-grpc_out=. --zrpc_out=. -m
  3. $ tree
  4. .
  5. ├── client
  6. ├── userclassservice
  7. └── userclassservice.go
  8. ├── userroleservice
  9. └── userroleservice.go
  10. └── userservice
  11. └── userservice.go
  12. ├── etc
  13. └── user.yaml
  14. ├── github.com
  15. └── example
  16. └── user
  17. ├── user.pb.go
  18. └── user_grpc.pb.go
  19. ├── go.mod
  20. ├── internal
  21. ├── config
  22. └── config.go
  23. ├── logic
  24. ├── userclassservice
  25. ├── userclassaddlogic.go
  26. ├── userclassdeletelogic.go
  27. ├── userclassinfologic.go
  28. ├── userclasslistlogic.go
  29. └── userclassupdatelogic.go
  30. ├── userroleservice
  31. ├── userroleaddlogic.go
  32. ├── userroledeletelogic.go
  33. ├── userroleinfologic.go
  34. ├── userrolelistlogic.go
  35. └── userroleupdatelogic.go
  36. └── userservice
  37. ├── loginlogic.go
  38. ├── userinfologic.go
  39. ├── userinfoupdatelogic.go
  40. └── userlistlogic.go
  41. ├── server
  42. ├── userclassservice
  43. └── userclassserviceserver.go
  44. ├── userroleservice
  45. └── userroleserviceserver.go
  46. └── userservice
  47. └── userserviceserver.go
  48. └── svc
  49. └── servicecontext.go
  50. ├── user.go
  51. └── user.proto
  52. 19 directories, 28 files

We can see through the directory structure that logic, server, and customer directories are grouped according to service.