控制器实现

基本介绍

结构化约束

控制器的输入与输出使用了结构体定义进行约束,结构化维护输入输出数据结构是推荐的方式。例如:

  1. // 账号唯一性检测请求参数,用于前后端交互参数格式约定
  2. type CheckPassportRequest struct {
  3. Passport string
  4. }

虽然仅有一个参数,但也采用了结构化定义,我们直接查看该结构体便可得知该接口的输入参数格式,而不用进入代码中去分析,从而极大提高维护效率。

结构体转换

结构体转换可以使用GetStruct或者Parse方法,其中Parse同时可以执行数据校验。结构体转换方法的参数都可以给定一个结构体的空指针,内部会自动初始化结构体对象,转换失败(例如提交参数不存在)不会执行初始化。例如:

  1. var data *SignUpRequest
  2. // 这里没有使用Parse而是仅用GetStruct获取对象,
  3. // 数据校验交给后续的service层统一处理。
  4. if err := r.GetStruct(&data); err != nil {
  5. response.JsonExit(r, 1, err.Error())
  6. }

数据校验

可以通过给结构体绑定v的标签进行设定校验规则以及定义的错误提示。例如:

  1. // 登录请求参数,用于前后端交互参数格式约定
  2. type SignInRequest struct {
  3. Passport string `v:"required#账号不能为空"`
  4. Password string `v:"required#密码不能为空"`
  5. }

数据传参

控制器负责接收、转换、校验、处理请求参数后,将所需的参数传递给调用的service层一个或者多个包方法,而不是直接将Request对象传递给service。例如:

  1. // 用户登录接口
  2. func (c *Controller) SignIn(r *ghttp.Request) {
  3. var data *SignInRequest
  4. if err := r.Parse(&data); err != nil {
  5. response.JsonExit(r, 1, err.Error())
  6. }
  7. if err := user.SignIn(data.Passport, data.Password, r.Session); err != nil {
  8. response.JsonExit(r, 1, err.Error())
  9. } else {
  10. response.JsonExit(r, 0, "ok")
  11. }
  12. }

需要注意的是,其中的Session对象也是通过控制器传递给service

Go的HTTP请求流程中,不存在”全局变量”获取请求参数的方式,只有根据service的需要按需传递参数。

实现代码

https://github.com/gogf/gf-demos/blob/master/app/api/user/user.go

  1. package user
  2. import (
  3. "github.com/gogf/gf-demos/app/service/user"
  4. "github.com/gogf/gf-demos/library/response"
  5. "github.com/gogf/gf/net/ghttp"
  6. )
  7. // 用户API管理对象
  8. type Controller struct{}
  9. // 注册请求参数,用于前后端交互参数格式约定
  10. type SignUpRequest struct {
  11. user.SignUpInput
  12. }
  13. // 用户注册接口
  14. func (c *Controller) SignUp(r *ghttp.Request) {
  15. var data *SignUpRequest
  16. // 这里没有使用Parse而是仅用GetStruct获取对象,
  17. // 数据校验交给后续的service层统一处理。
  18. if err := r.GetStruct(&data); err != nil {
  19. response.JsonExit(r, 1, err.Error())
  20. }
  21. if err := user.SignUp(&data.SignUpInput); err != nil {
  22. response.JsonExit(r, 1, err.Error())
  23. } else {
  24. response.JsonExit(r, 0, "ok")
  25. }
  26. }
  27. // 登录请求参数,用于前后端交互参数格式约定
  28. type SignInRequest struct {
  29. Passport string `v:"required#账号不能为空"`
  30. Password string `v:"required#密码不能为空"`
  31. }
  32. // 用户登录接口
  33. func (c *Controller) SignIn(r *ghttp.Request) {
  34. var data *SignInRequest
  35. if err := r.Parse(&data); err != nil {
  36. response.JsonExit(r, 1, err.Error())
  37. }
  38. if err := user.SignIn(data.Passport, data.Password, r.Session); err != nil {
  39. response.JsonExit(r, 1, err.Error())
  40. } else {
  41. response.JsonExit(r, 0, "ok")
  42. }
  43. }
  44. // 判断用户是否已经登录
  45. func (c *Controller) IsSignedIn(r *ghttp.Request) {
  46. if user.IsSignedIn(r.Session) {
  47. response.JsonExit(r, 0, "ok")
  48. } else {
  49. response.JsonExit(r, 1, "")
  50. }
  51. }
  52. // 用户注销/退出接口
  53. func (c *Controller) SignOut(r *ghttp.Request) {
  54. if err := user.SignOut(r.Session); err != nil {
  55. response.JsonExit(r, 1, "")
  56. }
  57. response.JsonExit(r, 0, "ok")
  58. }
  59. // 账号唯一性检测请求参数,用于前后端交互参数格式约定
  60. type CheckPassportRequest struct {
  61. Passport string
  62. }
  63. // 检测用户账号接口(唯一性校验)
  64. func (c *Controller) CheckPassport(r *ghttp.Request) {
  65. var data *CheckPassportRequest
  66. if err := r.Parse(&data); err != nil {
  67. response.JsonExit(r, 1, err.Error())
  68. }
  69. if data.Passport != "" && !user.CheckPassport(data.Passport) {
  70. response.JsonExit(r, 1, "账号已经存在")
  71. }
  72. response.JsonExit(r, 0, "ok")
  73. }
  74. // 账号唯一性检测请求参数,用于前后端交互参数格式约定
  75. type CheckNickNameRequest struct {
  76. Nickname string
  77. }
  78. // 检测用户昵称接口(唯一性校验)
  79. func (c *Controller) CheckNickName(r *ghttp.Request) {
  80. var data *CheckNickNameRequest
  81. if err := r.Parse(&data); err != nil {
  82. response.JsonExit(r, 1, err.Error())
  83. }
  84. if data.Nickname != "" && !user.CheckNickName(data.Nickname) {
  85. response.JsonExit(r, 1, "昵称已经存在")
  86. }
  87. response.JsonExit(r, 0, "ok")
  88. }
  89. // 获取用户详情
  90. func (c *Controller) Profile(r *ghttp.Request) {
  91. response.JsonExit(r, 0, "", user.GetProfile(r.Session))
  92. }