接口描述:api/v1
该目录中存放规范路由里api请求结构体与响应结构体描述文件,建议不同数据表分别写在不同文件中。图片示例如下:
控制器:controller
该目录中存放路由函数,通常的包名使用默认的controller。如下图所示:
如果有特殊用处的路由函数,可以在controller下建子目录,子目录中的文件使用另一个包名。
例如,我写的项目中发现有很多只有管理员权限才能使用的路由函数,为了方便管理,我在controller目录下建了manage子目录,将所有需要管理员权限才能使用的路由函数集中放在manage子目录中,包名都写成manage。
路由表cmd/cmd.go
路由表非常重要,如果路由表没有规划好,那么非常容易产生路由冲突,增加维护难度和维护成本。在编写路由表时请务必用心,做到规划合理、层级清晰。
在写路由表之前,首先理清思路,搞清楚以下内容:
路由根路径,项目名称
路由根路径指的是所有api的第一层级url名。建议要根据项目来命名,例如eventv1,前面单词event表明该项目名称,后面的v1表示接口版本号。
路由二级路径,页面名称
取名时建议综合考虑下面两种因素:
- 按页面取名:例如首页要用到的所有api,都放在/eventv1/home路径下。
- 按数据表取名:例如通知要用到的所有api,都放在/eventv1/notice路径下。
路由三级路径,动作名称
动作名称取名要规范、简洁、统一,我常用的动作名称如下:
get:获取
put:更改数据
add:增加数据
del:删除数据
patch:更改部分数据,如只更新详情信息。
其他的动作名,建议大家根据自己的需求取名。
路由四级路径,管理员权限api
通常api使用三级路由命名方式。但对于管理员权限api建议增加一个/manage层级,将所有需要管理员权限的api都放入该层级下,管理员鉴权的动作单独写一个鉴权的中间件。
以下写一个普通权限api与管理员权限api对比案例:
/eventv1/notice/get,通知获取(普通权限)
/eventv1/manage/notice/get,通知获取(管理员权限)
中间件
我写项目时常用的中间件有以下四个:
Auth:检查登录状况(前置中间件)
HandleReturn:处理返回数据(后置中间件)
ManageAuth:检查manage权限(前置中间件)
ManageUpdate:管理员更改数据后刷新缓存(后置中间件)
在规划路由要综合考虑中间件的使用。
路由表编码
以上步骤都理清以后,编写路由表就会轻松很多,基本可以做到游刃有余了,不会再有千头万绪理不清的感觉了。
以下节选一些我写的路由表代码做示例:
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
s := g.Server()
s.Group("/api", func(group *ghttp.RouterGroup) {
group.POST("/login", controller.Login) // 登录时不要加中间件,完整路由/api/login
group.POST("/logout", controller.Logout) // 登出时不要加中间件
})
s.Group("/api", func(group *ghttp.RouterGroup) {
group.Middleware(service.Middleware.Auth) // 检查登录状态的中间件
group.POST("/upload", controller.Upload) // 处理上传文件,完整路由/api/upload
})
s.Group("/api", func(group *ghttp.RouterGroup) {
group.Middleware(service.Middleware.Auth) // 检查登录状态的中间件
group.Middleware(service.Middleware.HandleReturn) // 处理返回内容的中间件
group.Group("/home", func(group *ghttp.RouterGroup) { // 首页
group.POST("/count/get", controller.CountGet) // 统计待处理记录数,完整路由/api/home/count/get
group.Group("/todo", func(group *ghttp.RouterGroup) { // TOdo表,工作交接
group.POST("/add", controller.TodoAdd) // 待办事件增加
group.POST("/put", controller.TodoPut) // 待办事件处理,完整路由/api/home/todo/put
group.POST("/get", controller.TodoGet) // 待办事件查询
group.POST("/del", controller.TodoDel) // 待办事件删除
group.POST("/sign", controller.TodoSign) // 待办事件签到
})
})
group.Group("/manage", func(group *ghttp.RouterGroup) { // 需要“manage”权限
group.Middleware(service.Middleware.ManageAuth) // 检查manage权限的中间件
group.Middleware(service.Middleware.ManageUpdate) // 刷新缓存的中间件
group.Group("/notice", func(group *ghttp.RouterGroup) { // Notice表
group.POST("/add", manage.NoticeAdd) // 通知增加
group.POST("/del", manage.NoticeDel) // 通知删除
group.POST("/put", manage.NoticePut) // 通知修改,完整路由/api/manage/notice/put
group.POST("/get", manage.NoticeGetManage) // 通知查询,编辑权限
})
最后
以上内容是我一家之言,所有路由统一用post接口,不一定符合所有人的胃口,也不符合restful接口规范。但我个人觉得按以上方式写的路由清晰,有一定参考价值,所以分享给大家。如有不妥之处欢迎留言讨论。
另外,关于规范路由的内容还有一篇相关的博客“关于goframe2.0规范路由——请求结构体与响应结构体”。
再附一个规范路由自动生成的swagger