(go 空值相关) gin 怎么检测 query 或 form 参数存不存在?

2020-08-04 19:51:55 +08:00
 hakono

gin 获取表单参数的方法是 c.PostForm("name"),当 name 这个参数不存在时,会默认返回空字符串 ""

然后问题来了,如果用户 POST 请求 api,在 form 里传入了 name= 这样的数据的话,通过 c.PostForm("name") 也将获取到空字符串 "" ,这就导致程序根本没法区分这个空字符串是因为用户没有指定 name 这个参数,还是将 name 这个参数设定成了空字符串

也许会有人觉得这两者没有区别,但是考虑下面这个 API 的话,两者会截然不同:

请求一个 API,可以更新数据库中指定的一些字段,没有指定的字段则不做任何更新。 在这个 API 中, 用户在 post form 中 指定了 name= 的话意味着将 name 字段清空,设置成 "" , 而不指定 name 参数的话则意味着不对 name 字段做操作

4339 次点击
所在节点    Go 编程语言
11 条回复
kaifang
2020-08-04 19:54:53 +08:00
gin 自带校验器,你这种情况可以用检验器解决
https://gin-gonic.com/docs/examples/bind-form-data-request-with-custom-struct/
hakono
2020-08-04 20:07:06 +08:00
@kaifang 感谢回复,校验器的话也有在用不过不太熟悉,对于怎么解决我这种情况没有头绪

我尝试过如下代码:

type Name struct {
Name string `form:"name" binding:"required"`
}
n := new(Name)
e := c.ShouldBind(n)

这样子的话即便用户在 form 里指定了 `name=` ,也依旧会被当成没有提供 name 这种参数而报错:
Key: 'Name.Name' Error:Field validation for 'Name' failed on the 'required' tag
hakono
2020-08-04 20:16:22 +08:00
@kaifang 搜了下发现 v,err := c.GetPostForm("name") 可以确认存不存在。但是现在我更倾向使用 Bind 配合校验器来处理输入的数据,请问 gin 自带的校验器有没有方法确认一个参数是否存在?
panlatent
2020-08-04 20:19:30 +08:00
golang 中的类型默认初始化零值,这种参数解析可以大体分为有值(非 null )和无值( null ),有值又分为非零值和零值,所以基本类型是无法表示这三种状态的, 且 validator 库默认会把零值视为必填参数为空。。

可以借鉴 NullXXX 这种类型,并编写支持 validator 验证 / DB Parse / JSON Marshal/Unmarshal 等方法。
panlatent
2020-08-04 20:26:00 +08:00
在我的实际使用中, 实体标志( ID 属性)没有使用 null 值的需求,零值就相当于 null,POST 和 PUT 方法会提交需要的所有字段,以字符串属性为例, 不存在某个 string = “” 表示跳过赋值的情况,所以也用不到 NullType ; 对于 PATCH 这种,有时候业务逻辑是不允许某个属性为空的, 这时仍不需要 NullType, 剩下的情况可能就需要 NullString 这种来上场了。
hakono
2020-08-04 20:40:38 +08:00
@panlatent 是的,目前是在编写一个 PATCH 的 API,更新字段,可更新的字段可以为空,然后被这 go 的 null,空值问题搞得焦头烂额的。Python,PHP 等动态语言的话可以很轻松通过赋予 null 或 None 判断,Go 就懵了(才刚学 Go )

Gin 虽然有个函数 GetPostForm 可以支持检测存不存在,但既然 gin 有 validator 肯定还是倾向于使用 validator

这样的话一想到要如你所说用 struct 写个 NullableString 就感觉头疼。。。。
nomansky
2020-08-04 20:44:42 +08:00
用指针类型*string
panlatent
2020-08-04 20:48:04 +08:00
@hakono 工作量不大,基础设置,早晚都得造,避免不了。 可以从 sql.NullString 继承个
labulaka521
2020-08-04 20:56:16 +08:00
前段时间遇到过这种问题,某个参数是必填的,但是可选的值包括此类型值的零值,最后把这个类型的值设置为指针类型的方式解决的
gin 的一个例子 https://play.golang.org/p/cnOMvObJ5Kb
lovejoy
2020-08-04 22:04:12 +08:00
也碰到过类似问题,最后发现只能用指针的方式搞。
vvmint233
2020-08-04 22:24:17 +08:00
那么为什么不让前端把整个数据架构传过来然后一起更新呢, {"a": "1", "b": "2"}, 变更了 b, 整个结构变成了{"a": "1", "b": "3"}, 前端将 a 和 b 一起传过来, 这样就不需要考虑有没有设置空值的问题了, 只需要考虑零值的问题

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/695623

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX