输入处理

总体来说,处理输入主要依赖于 Controller 提供的方法。而具体输入可以来源于:

  • 路径参数:这一部分主要是指参数路由
  • 查询参数
  • 请求体:要想从请求体里面读取数据,大多数时候将BConfig.CopyRequestBody 设置为true就足够了。而如果你是创建了多个 web.Server,那么必须每一个Server实例里面的配置都将CopyRequestBody设置为true

而获取参数的方法可以分成两大类:

  • 第一类是以 Get 为前缀的方法:这一大类的方法,主要获得某个特定参数的值
  • 第二类是以 Bind 为前缀的方法:这一大类的方法,试图将输入转化为结构体

Get 类方法

针对这一类方法,Beego 主要从两个地方读取:查询参数和表单,如果两个地方都有相同名字的参数,那么 Beego 会返回表单里面的数据。例如最简单的例子:

  1. type MainController struct {
  2. web.Controller
  3. }
  4. func (ctrl *MainController) Post() {
  5. name := ctrl.GetString("name")
  6. if name == "" {
  7. ctrl.Ctx.WriteString("Hello World")
  8. return
  9. }
  10. ctrl.Ctx.WriteString("Hello " + name)
  11. }

当我们访问:

  • 路径 localhost:8080?name=a: 这是使用查询参数的形式,那么会输出 Hello, a
  • 路径 localhost:8080,而后表单里面提交了name=b,那么会输出b
  • 路径 localhost:8080?name=a,并且表单提交了name=b,那么会输出b

这一类的方法也允许传入默认值,例如:

  1. func (ctrl *MainController) Get() {
  2. name := ctrl.GetString("name", "Tom")
  3. ctrl.Ctx.WriteString("Hello " + name)
  4. }

如果我们没有传入name参数,那么就会使用Tom作为name的值,例如我们访问GET localhost:8080的时候,就会输出 Hello Tom

需要注意的是,GetString的方法签名是:

  1. func (c *Controller) GetString(key string, def ...string) string {
  2. // ...
  3. }

要注意的是,虽然def被声明为不定参数,但是实际上,Beego 只会使用第一个默认值,后面的都会被忽略。

这一类方法签名和行为都是类似的,它们有:

  • GetString(key string, def ...string) string
  • GetStrings(key string, def ...[]string) []string
  • GetInt(key string, def ...int) (int, error)
  • GetInt8(key string, def ...int8) (int8, error)
  • GetUint8(key string, def ...uint8) (uint8, error)
  • GetInt16(key string, def ...int16) (int16, error)
  • GetUint16(key string, def ...uint16) (uint16, error)
  • GetInt32(key string, def ...int32) (int32, error)
  • GetUint32(key string, def ...uint32) (uint32, error)
  • GetInt64(key string, def ...int64) (int64, error)
  • GetUint64(key string, def ...uint64) (uint64, error)
  • GetBool(key string, def ...bool) (bool, error)
  • GetFloat(key string, def ...float64) (float64, error)

这里要注意到,GetStringGetStrings 本身在设计的时候并没有设计返回 error,所以无法拿到错误。

Bind 类方法

大多数时候,我们还需要把输入转换为结构体,Beego 提供了一系列的方法来完成输入到结构体的绑定。

这部分方法是直接定义在 Context 结构体上的,所以用户可以直接操作 Context 实例。为了简化操作,我们在Controller上也定义了类似的方法。

例如:

  1. // 要设置 web.BConfig.CopyRequestBody = true
  2. type MainController struct {
  3. web.Controller
  4. }
  5. func (ctrl *MainController) Post() {
  6. user := User{}
  7. err := ctrl.BindJSON(&user)
  8. if err != nil {
  9. ctrl.Ctx.WriteString(err.Error())
  10. return
  11. }
  12. ctrl.Ctx.WriteString(fmt.Sprintf("%v", user))
  13. }
  14. type User struct {
  15. Age int `json:"age"`
  16. Name string `json:"name"`
  17. }

Bind这一大类有多个方法:

  • Bind(obj interface{}) error: 默认是依据输入的 Content-Type字段,来判断该如何反序列化;
  • BindYAML(obj interface{}) error: 处理YAML输入
  • BindForm(obj interface{}) error: 处理表单输入
  • BindJSON(obj interface{}) error: 处理JSON输入
  • BindProtobuf(obj proto.Message) error: 处理proto输入
  • BindXML(obj interface{}) error: 处理XML输入

在使用特定格式的输入的时候,别忘记设置标签(Tag),例如我们例子里面的json:"age",不同格式的输入,其标签是不是一样的。

需要注意的是,虽然我们提供了一个根据Content-Type来判断如何绑定的,但是我们更加推荐用户使用指定格式的绑定方法。

一个接口,应该只接收特定某种格式的输入,例如只接收 JSON,而不应该可以处理多种输入

在早期,Beego 还有一个类似于BindForm的方法:ParseForm(obj interface{}) error,这两个方法效果是一致的。

路径参数

我们在路由定义——参数路由里面介绍过了如何获取路径参数。

早期 Bind 方法

在 Beego 的Input中定义了一系列的方法,用于读取参数。这一类方法很类似于 Get 一族的方法。所以用户可以酌情使用。

例如请求地址如下

  1. ?id=123&isok=true&ft=1.2&ol[0]=1&ol[1]=2&ul[]=str&ul[]=array&user.Name=astaxie
  2. var id int
  3. this.Ctx.Input.Bind(&id, "id") //id ==123
  4. var isok bool
  5. this.Ctx.Input.Bind(&isok, "isok") //isok ==true
  6. var ft float64
  7. this.Ctx.Input.Bind(&ft, "ft") //ft ==1.2
  8. ol := make([]int, 0, 2)
  9. this.Ctx.Input.Bind(&ol, "ol") //ol ==[1 2]
  10. ul := make([]string, 0, 2)
  11. this.Ctx.Input.Bind(&ul, "ul") //ul ==[str array]
  12. user struct{Name}
  13. this.Ctx.Input.Bind(&user, "user") //user =={Name:"astaxie"}

相关内容