在本示例,我们尝试通过数据结构化的方式,解决上一章节的参数名称硬编码问题。

请求对象

我们定义一个请求的数据结构来接收客户端提交的参数信息:

  1. type HelloReq struct {
  2. Name string // 名称
  3. Age int // 年龄
  4. }

太棒了,看起来我们既可以对参数进行注释描述,也能确定参数的类型,不再需要参数名称硬编码。

示例代码

我们调整我们前面的Web Server程序如下:

main.go

  1. package main
  2. import (
  3. "github.com/gogf/gf/v2/frame/g"
  4. "github.com/gogf/gf/v2/net/ghttp"
  5. )
  6. type HelloReq struct {
  7. Name string // 名称
  8. Age int // 年龄
  9. }
  10. func main() {
  11. s := g.Server()
  12. s.BindHandler("/", func(r *ghttp.Request) {
  13. var req HelloReq
  14. if err := r.Parse(&req); err != nil {
  15. r.Response.Write(err.Error())
  16. return
  17. }
  18. if req.Name == "" {
  19. r.Response.Write("name should not be empty")
  20. return
  21. }
  22. if req.Age <= 0 {
  23. r.Response.Write("invalid age value")
  24. return
  25. }
  26. r.Response.Writef(
  27. "Hello %s! Your Age is %d",
  28. req.Name,
  29. req.Age,
  30. )
  31. })
  32. s.SetPort(8000)
  33. s.Run()
  34. }

在本示例中:

  • 我们通过r.Parse方法将请求参数映射到请求对象上,随后可以通过对象的方式来使用参数。 r.Parse方法支持自动解析客户端提交参数,并赋值到指定对象上。 内部有固定的名称映射逻辑,您将在开发手册的类型转换组件中详细了解到,这里不作过多介绍。
  • 同时,我们在本示例中增加了校验逻辑,NameAge参数不能为空。

执行结果

运行后,我们访问 http://127.0.0.1:8000/?name=john&age=18 可以看到,页面输出结果符合预期。

img.png

我们尝试一下错误的参数请求 http://127.0.0.1:8000/ 可以看到,参数被按照预期校验,页面输出结果同样符合预期

img_2.png

学习小结

在本章节中,我们学会了通过结构化请求对象的方式来规避参数名称硬编码的问题, 也能很好地维护参数的名称、描述和类型定义。

但在该示例代码中,同样有值得改进的地方:

  • 其中的r.Parse是属于业务无关的操作,理应当独立于业务逻辑之外处理。
  • 如果接口比较多的情况下,所有的接口中都要重复进行r.Parse操作,比较繁琐。
  • 关于数据校验,如果接口的参数比较多,进行大量的if数据校验操作太过于繁琐。

是否有更好的方式来简化并解决这些问题呢?答案是肯定的,我们下一个章节尝试解决这一问题。