首页 > 编程知识 正文

cannot contact any KDC for(ollydbg最多同时设置几个内存断点)

时间:2023-05-05 03:10:13 阅读:83822 作者:1553

在我们写的大多数API代码中,实际上需要传递参数。 无论是path、query string还是body方法,gin都提供了一组绑定方法,用于将这些参数绑定到单个对象,以便可以在结构标签中验证这些参数。 我不知道是不是和以前一样

创建/更新接口时,id可能只有一个不同。 可以重复使用代码吗? 可以通过model层的结构直接绑定参数吗? (转自) 3359 zhuan LAN.zhi Hu.com/p/91312616

整理:地鼠文档: www.topgoer.cn

其次,从这些问题出发,利用go组合的特点,介绍一些参数绑定上的小技巧

参数绑定技巧

1. 复用创建/更新时的参数

//用户参数用户参数

类型用户参数结构

名称字符串` JSon : '名称'绑定: '需要'

密码串` JSon : '密码'绑定: '需要'

}

//创建用户参数创建用户

类型创建用户参数结构

用户参数

}

//更新用户参数用户更新

类型更新用户参数结构

用户参数

身份绑定:需要

在绑定}

2. 用 model 层的 struct 绑定参数

参数时,如果如上所述为每个参数分别创建绑定,则在Model层创建数据库记录时需要手动进行转换。 如果需要分别这样写的话,会很麻烦。

这是原来的用户表

//model/model.go

//模型默认模型

类型模型结构

id单元: ' id ' Gorm : '主要密钥'

createdattime.time ` JSon : ' created _ at ' `

更新时间.时间` JSon : '更新_ at ' `

elete dat * time.time ` JSon : ' deleted _ at ' SQL : '索引` `

}

//model /用户. go

//用户用户表

类型用户结构

模特

名称字符串` JSon : '名称`

密码串` JSon : `密码`

此时,“binding:”-“利用忽略字段的功能,可以与struct组合,将api的参数和model关联起来,减少结构体变换的代码

//model/model.go

//模型默认模型

类型模型结构

id单元: ' id ' Gorm : '主要密钥'

createdattime.time ` JSon : ' created _ at '绑定: '-` `

更新时间.时间` JSon : '更新_ at '绑定: '-`

elete dat * time.time ` JSon : ' deleted _ at ' SQL : '索引'绑定: '-` `

}

//model /用户. go

//用户用户表

类型用户结构

模特

名称字符串` JSon : '名称'绑定: '需要'

密码串` JSon : '密码'绑定: '需要'

}

//API /用户. go

//用户参数用户参数

类型用户参数结构

模型用户

}

//创建用户参数创建用户

类型创建用户参数结构

用户参数

id单元: ' id ' Gorm : '主要密钥'绑定: '-`

}

//更新用户参数用户更新

类型升级

dateUserParams struct { UserParams }

3. 使用 ShouldBind 而不是 Bind

Bind 方法会自动将 http status 设置为 400, 然后报错,但是我们往往会需要携带更多的信息返回,或者返回不同的 status 这时候往往会出现下面这样的警告,而使用 ShouldBind 可以避免此类问题

[WARNING] Headers were already written. Wanted to override status code 400 with 200

4. 多次绑定 request body 数据

这是官方文档的一个示例,一般情况第二次读取 request body 的数据就会出现 EOF 的错误,因为 c.Request.Body 不可以重用

type formA struct { Foo string `json:"foo" binding:"required"` } type formB struct { Bar string `json:"bar" binding:"required"` } func SomeHandler(c *gin.Context) { objA := formA{} objB := formB{} // c.ShouldBind 使用了 c.Request.Body,不可重用。 if errA := c.ShouldBind(&objA); errA == nil { c.String(http.StatusOK, `the body should be formA`) // 因为现在 c.Request.Body 是 EOF,所以这里会报错。 } else if errB := c.ShouldBind(&objB); errB == nil { c.String(http.StatusOK, `the body should be formB`) } else { ... } }

gin 1.4 之后官方提供了一个 ShouldBindBodyWith 的方法,可以支持重复绑定,原理就是将 body 的数据缓存了下来,但是二次取数据的时候还是得用 ShouldBindBodyWith 才行,直接用 ShouldBind 还是会报错的。

func SomeHandler(c *gin.Context) { objA := formA{} objB := formB{} // 读取 c.Request.Body 并将结果存入上下文。 if errA := c.ShouldBindBodyWith(&objA, binding.JSON); errA == nil { c.String(http.StatusOK, `the body should be formA`) // 这时, 复用存储在上下文中的 body。 } else if errB := c.ShouldBindBodyWith(&objB, binding.JSON); errB == nil { c.String(http.StatusOK, `the body should be formB JSON`) // 可以接受其他格式 } else { ... } }

这种方式其实有个问题,什么情况下我们会去多次读取 body 的数据,其实在中间件中我们是需要用到,有的中间件需要读取参数做一些处理,例如权限中间件需要获取当前资源的id,判断当前用户是否有权限,如果这个时候直接使用 ShouldBindBodyWith 会导致之后的所有的接口都修改才行,十分的不优雅,下面提供一种不用影响后续使用的方法

func startPage(c *gin.Context) { var ( p1 Person p2 Person ) buf := &bytes.Buffer{} tea := io.TeeReader(c.Request.Body, buf) body, err := ioutil.ReadAll(tea) if err != nil { log.Panicf("read body err: %+v", err) } c.Request.Body = ioutil.NopCloser(buf) // read buf ... if err := binding.JSON.BindBody(body, &p1); err != nil { log.Panic("p1", err) } log.Println("p1", p1) // use ShouldBind again .. if err := c.ShouldBind(&p2); err != nil { log.Panic("p2", err) } log.Println("p2", p2) c.String(200, "Success") } // output // 2019/11/06 23:10:04 p1 {hello world} // 2019/11/06 23:10:04 p2 {hello world} // [GIN] 2019/11/06 - 23:10:04 | 200 | 27.0400917s | ::1 | POST /testing

这三行也适用于其他需要多次读取 io.Reader 的情况

buf := &bytes.Buffer{} tea := io.TeeReader(c.Request.Body, buf) body, err := ioutil.ReadAll(tea)

总结

这篇文章从参数绑定的问题出发,为大家介绍了两种组合参数的小技巧,提供了使用参数绑定的时候的一个建议,并且提出了非官方,侵入性小的的多次读取 request body 的方式。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。