API Route Groups
Overview
Section titled “Overview”In go-zero, we declared HTTP service via api language, and then generated HTTP service code via goctl, after our systematic introduction to API norm.
In HTTP service development, as business develops, our services interfaces will grow, and the number of code files generated (handler, logic files, etc.) will grow, when some of the generated code files will need to be aggregated in order to facilitate development and maintenance.
Service Group
Section titled “Service Group”Assume that we have a user service, we have multiple interfaces below:
https://example.com/v1/user/loginhttps://example.com/v1/user/infohttps://example.com/v1/user/info/updatehttps://example.com/v1/user/list
https://example.com/v1/user/role/listhttps://example.com/v1/user/role/updatehttps://example.com/v1/user/role/infohttps://example.com/v1/user/role/addhttps://example.com/v1/user/role/delete
https://example.com/v1/user/class/listhttps://example.com/v1/user/class/updatehttps://example.com/v1/user/class/infohttps://example.com/v1/user/class/addhttps://example.com/v1/user/class/deleteLet’s first look at api language prophylactic without grouping:
syntax = "v1"
type ( UserLoginReq{} UserInfoReq{} UserLoginResp{} UserInfoResp{} UserInfoUpdateReq{} UserInfoUpdateResp{})
type ( UserRoleReq{} UserRoleResp{} UserRoleUpdateReq{} UserRoleUpdateResp{} UserRoleAddReq{} UserRoleAddResp{} UserRoleDeleteReq{} UserRoleDeleteResp{})
type ( UserClassReq{} UserClassResp{} UserClassUpdateReq{} UserClassUpdateResp{} UserClassAddReq{} UserClassAddResp{} UserClassDeleteReq{} UserClassDeleteResp{})@server( prefix: /v1)service user-api { @handler UserLogin post /user/login (UserLoginReq) returns (UserLoginResp)
@handler UserInfo post /user/info (UserInfoReq) returns (UserInfoResp)
@handler UserInfoUpdate post /user/info/update (UserInfoUpdateReq) returns (UserInfoUpdateResp)
@handler UserList get /user/list returns ([]UserInfoResp)
@handler UserRoleList get /user/role/list returns ([]UserRoleResp)
@handler UserRoleUpdate get /user/role/update (UserRoleUpdateReq) returns (UserRoleUpdateResp)
@handler UserRoleInfo get /user/role/info (UserRoleReq) returns (UserRoleResp)
@handler UserRoleAdd get /user/role/add (UserRoleAddReq) returns (UserRoleAddResp)
@handler UserRoleDelete get /user/role/delete (UserRoleDeleteReq) returns (UserRoleDeleteResp)
@handler UserClassList get /user/class/list returns ([]UserClassResp)
@handler UserClassUpdate get /user/class/update (UserClassUpdateReq) returns (UserClassUpdateResp)
@handler UserClassInfo get /user/class/info (UserClassReq) returns (UserClassResp)
@handler UserClassAdd get /user/class/add (UserClassAddReq) returns (UserClassAddResp)
@handler UserClassDelete get /user/class/delete (UserClassDeleteReq) returns (UserClassDeleteResp)}Code directory structure generated without a group below:
.├── etc│ └── user-api.yaml├── internal│ ├── config│ │ └── config.go│ ├── handler│ │ ├── routes.go│ │ ├── userclassaddhandler.go│ │ ├── userclassdeletehandler.go│ │ ├── userclassinfohandler.go│ │ ├── userclasslisthandler.go│ │ ├── userclassupdatehandler.go│ │ ├── userinfohandler.go│ │ ├── userinfoupdatehandler.go│ │ ├── userlisthandler.go│ │ ├── userloginhandler.go│ │ ├── userroleaddhandler.go│ │ ├── userroledeletehandler.go│ │ ├── userroleinfohandler.go│ │ ├── userrolelisthandler.go│ │ └── userroleupdatehandler.go│ ├── logic│ │ ├── userclassaddlogic.go│ │ ├── userclassdeletelogic.go│ │ ├── userclassinfologic.go│ │ ├── serclasslistlogic.go│ │ ├── userclassupdatelogic.go│ │ ├── userinfologic.go│ │ ├── userinfoupdatelogic.go│ │ ├── userlistlogic.go│ │ ├── userloginlogic.go│ │ ├── userroleaddlogic.go│ │ ├── userroledeletelogic.go│ │ ├── userroleinfologic.go│ │ ├── userrolelistlogic.go│ │ └── userroleupdatelogic.go│ ├── svc│ │ └── servicecontext.go│ └── types│ └── types.go├── user.api└── user.go
7 directories, 35 filesSince we do not group in groups, all the files in the generated code handler and the log directory are blown together. This directory structure is not well managed and read in the project, and we follow as user,role,class for grouping. In api language, we can group by using server group keywords in the group groups below:
syntax = "v1"
type ( UserLoginReq {} UserInfoReq {} UserLoginResp {} UserInfoResp {} UserInfoUpdateReq {} UserInfoUpdateResp {})
type ( UserRoleReq {} UserRoleResp {} UserRoleUpdateReq {} UserRoleUpdateResp {} UserRoleAddReq {} UserRoleAddResp {} UserRoleDeleteReq {} UserRoleDeleteResp {})
type ( UserClassReq {} UserClassResp {} UserClassUpdateReq {} UserClassUpdateResp {} UserClassAddReq {} UserClassAddResp {} UserClassDeleteReq {} UserClassDeleteResp {})
@server ( prefix: /v1 group: user)service user-api { @handler UserLogin post /user/login (UserLoginReq) returns (UserLoginResp)
@handler UserInfo post /user/info (UserInfoReq) returns (UserInfoResp)
@handler UserInfoUpdate post /user/info/update (UserInfoUpdateReq) returns (UserInfoUpdateResp)
@handler UserList get /user/list returns ([]UserInfoResp)}
@server ( prefix: /v1 group: role)service user-api { @handler UserRoleList get /user/role/list returns ([]UserRoleResp)
@handler UserRoleUpdate get /user/role/update (UserRoleUpdateReq) returns (UserRoleUpdateResp)
@handler UserRoleInfo get /user/role/info (UserRoleReq) returns (UserRoleResp)
@handler UserRoleAdd get /user/role/add (UserRoleAddReq) returns (UserRoleAddResp)
@handler UserRoleDelete get /user/role/delete (UserRoleDeleteReq) returns (UserRoleDeleteResp)}
@server ( prefix: /v1 group: class)service user-api { @handler UserClassList get /user/class/list returns ([]UserClassResp)
@handler UserClassUpdate get /user/class/update (UserClassUpdateReq) returns (UserClassUpdateResp)
@handler UserClassInfo get /user/class/info (UserClassReq) returns (UserClassResp)
@handler UserClassAdd get /user/class/add (UserClassAddReq) returns (UserClassAddResp)
@handler UserClassDelete get /user/class/delete (UserClassDeleteReq) returns (UserClassDeleteResp)}Let’s look again at the code-generation directory structure after grouping:
.├── etc│ └── user-api.yaml├── internal│ ├── config│ │ └── config.go│ ├── handler│ │ ├── class│ │ │ ├── userclassaddhandler.go│ │ │ ├── userclassdeletehandler.go│ │ │ ├── userclassinfohandler.go│ │ │ ├── userclasslisthandler.go│ │ │ └── userclassupdatehandler.go│ │ ├── role│ │ │ ├── userroleaddhandler.go│ │ │ ├── userroledeletehandler.go│ │ │ ├── userroleinfohandler.go│ │ │ ├── userrolelisthandler.go│ │ │ └── userroleupdatehandler.go│ │ ├── routes.go│ │ └── user│ │ ├── userinfohandler.go│ │ ├── userinfoupdatehandler.go│ │ ├── userlisthandler.go│ │ └── userloginhandler.go│ ├── logic│ │ ├── class│ │ │ ├── userclassaddlogic.go│ │ │ ├── userclassdeletelogic.go│ │ │ ├── userclassinfologic.go│ │ │ ├── userclasslistlogic.go│ │ │ └── userclassupdatelogic.go│ │ ├── role│ │ │ ├── userroleaddlogic.go│ │ │ ├── userroledeletelogic.go│ │ │ ├── userroleinfologic.go│ │ │ ├── userrolelistlogic.go│ │ │ └── userroleupdatelogic.go│ │ └── user│ │ ├── userinfologic.go│ │ ├── userinfoupdatelogic.go│ │ ├── userlistlogic.go│ │ └── userloginlogic.go│ ├── svc│ │ └── servicecontext.go│ └── types│ ├── class│ │ └── class.go│ ├── role│ │ └── role.go│ └── user│ └── user.go└── user.go
17 directories, 36 filesBy clustering we can easily group different business logic into different directories so that different business logic can be managed easily.