V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
hakono
V2EX  ›  Go 编程语言

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

  •  
  •   hakono · 2020-08-04 19:51:55 +08:00 · 4503 次点击
    这是一个创建于 1563 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

    11 条回复    2020-08-04 22:24:17 +08:00
    kaifang
        1
    kaifang  
       2020-08-04 19:54:53 +08:00
    gin 自带校验器,你这种情况可以用检验器解决
    https://gin-gonic.com/docs/examples/bind-form-data-request-with-custom-struct/
    hakono
        2
    hakono  
    OP
       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
        3
    hakono  
    OP
       2020-08-04 20:16:22 +08:00
    @kaifang 搜了下发现 v,err := c.GetPostForm("name") 可以确认存不存在。但是现在我更倾向使用 Bind 配合校验器来处理输入的数据,请问 gin 自带的校验器有没有方法确认一个参数是否存在?
    panlatent
        4
    panlatent  
       2020-08-04 20:19:30 +08:00
    golang 中的类型默认初始化零值,这种参数解析可以大体分为有值(非 null )和无值( null ),有值又分为非零值和零值,所以基本类型是无法表示这三种状态的, 且 validator 库默认会把零值视为必填参数为空。。

    可以借鉴 NullXXX 这种类型,并编写支持 validator 验证 / DB Parse / JSON Marshal/Unmarshal 等方法。
    panlatent
        5
    panlatent  
       2020-08-04 20:26:00 +08:00
    在我的实际使用中, 实体标志( ID 属性)没有使用 null 值的需求,零值就相当于 null,POST 和 PUT 方法会提交需要的所有字段,以字符串属性为例, 不存在某个 string = “” 表示跳过赋值的情况,所以也用不到 NullType ; 对于 PATCH 这种,有时候业务逻辑是不允许某个属性为空的, 这时仍不需要 NullType, 剩下的情况可能就需要 NullString 这种来上场了。
    hakono
        6
    hakono  
    OP
       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
        7
    nomansky  
       2020-08-04 20:44:42 +08:00   ❤️ 1
    用指针类型*string
    panlatent
        8
    panlatent  
       2020-08-04 20:48:04 +08:00
    @hakono 工作量不大,基础设置,早晚都得造,避免不了。 可以从 sql.NullString 继承个
    labulaka521
        9
    labulaka521  
       2020-08-04 20:56:16 +08:00
    前段时间遇到过这种问题,某个参数是必填的,但是可选的值包括此类型值的零值,最后把这个类型的值设置为指针类型的方式解决的
    gin 的一个例子 https://play.golang.org/p/cnOMvObJ5Kb
    lovejoy
        10
    lovejoy  
       2020-08-04 22:04:12 +08:00
    也碰到过类似问题,最后发现只能用指针的方式搞。
    vvmint233
        11
    vvmint233  
       2020-08-04 22:24:17 +08:00
    那么为什么不让前端把整个数据架构传过来然后一起更新呢, {"a": "1", "b": "2"}, 变更了 b, 整个结构变成了{"a": "1", "b": "3"}, 前端将 a 和 b 一起传过来, 这样就不需要考虑有没有设置空值的问题了, 只需要考虑零值的问题
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5910 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 02:41 · PVG 10:41 · LAX 18:41 · JFK 21:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.