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

golang 怎么判断是否传递了数值类型

  •  
  •   123string · 2019-01-29 17:02:09 +08:00 · 5069 次点击
    这是一个创建于 2158 天前的主题,其中的信息可能已经有所发展或是发生改变。

    一个 post 请求里面的数值类型传递 0 和不传递,解析到结构体中都是 0,要怎么判断是否传递了呢

    30 条回复    2019-01-30 17:10:46 +08:00
    Vegetable
        1
    Vegetable  
       2019-01-29 17:09:35 +08:00
    专门要判断的话就先赋值改动默认值.比如-1,应该能解决.
    Immortal
        2
    Immortal  
       2019-01-29 17:12:21 +08:00
    解析前判断
    123string
        3
    123string  
    OP
       2019-01-29 17:19:26 +08:00
    @Immortal 解析前怎么判断
    xkeyideal
        4
    xkeyideal  
       2019-01-29 17:22:57 +08:00
    指针,我去翻个例子给你
    lyatqh
        5
    lyatqh  
       2019-01-29 17:23:00 +08:00
    值类型改成指针类型就可以了;比如 int 类型改成*int,如果不传是 nil 而不是 0。
    也可以用这个库 https://github.com/mattn/go-nulltype
    xkeyideal
        6
    xkeyideal  
       2019-01-29 17:24:25 +08:00   ❤️ 2
    type NodeXXX struct {
    Date string `json:"date"`
    Count *int32 `json:"count"`
    }
    justfly
        7
    justfly  
       2019-01-29 17:26:51 +08:00
    你这个需求,只能别解析到结构体里面,解析到 map 里面了
    GuangXiN
        8
    GuangXiN  
       2019-01-29 17:28:55 +08:00
    ```go
    func myHandler(w http.ResponseWriter,r *http.Request) {
    err := r.ParseForm()
    if err != nil {
    panic(err)
    }
    value, ok := r.PostForm["some_field"];
    if !ok {
    // some_field 不存在
    }
    // ...
    }
    ```
    GuangXiN
        9
    GuangXiN  
       2019-01-29 17:30:12 +08:00
    原来 V2EX 不支持 markdown 语法么
    Immortal
        10
    Immortal  
       2019-01-29 17:30:13 +08:00
    8l 那样的
    解析前默认就是在 request 的 map 里的
    123string
        11
    123string  
    OP
       2019-01-29 17:46:20 +08:00
    @GuangXiN json 格式的
    Immortal
        12
    Immortal  
       2019-01-29 17:48:17 +08:00
    json 看 6l
    strive
        13
    strive  
       2019-01-29 17:55:04 +08:00
    //GetInt 获取 int 数据,不是有效的数字则返回默然值或 0,默认值传-1
    func GetInt(v interface{}, def ...int) int {
    value := fmt.Sprintf("%v", v)
    if strings.Contains(strings.ToUpper(value), "E+") {
    var n float64
    _, err := fmt.Sscanf(value, "%e", &n)
    if err == nil {
    return int(n)
    }
    if len(def) > 0 {
    return def[0]
    }
    }
    if value, err := strconv.Atoi(value); err == nil {
    return value
    }
    if len(def) > 0 {
    return def[0]
    }
    return 0
    }
    123string
        14
    123string  
    OP
       2019-01-29 18:16:54 +08:00
    @justfly 解析到 map 怎么解析的?
    Muninn
        15
    Muninn  
       2019-01-29 18:30:54 +08:00
    目前主流的有两种办法

    一种是 gin 推荐的用一个校验的 package 去做。 在结构体上用 tag 描述校验规则,如果不让为空可以直接报错。 但是这个其实达不到有些目的。

    我是用的额外的结构体+指针类型。 根据是否是 nil 决定怎么赋值。
    Muninn
        16
    Muninn  
       2019-01-29 18:32:06 +08:00
    123string
        17
    123string  
    OP
       2019-01-29 18:33:53 +08:00
    @Muninn 谢谢
    rayhy
        18
    rayhy  
       2019-01-29 18:35:37 +08:00
    啊我最近写项目也遇到这个问题了!确实搞起来有点麻烦,但好在有人已经写好库了,我最近一直用: https://godoc.org/gopkg.in/guregu/null.v3

    思路是这样:
    新建一个 struct,

    type NullInt64 struct {
    Int64 int64
    Valid bool // Valid is true if Int64 is not NULL
    }

    然后给这个 struct 实现 解析 json 时需要的 MarshalJSON 那一套方法。

    最终代码如下可以参考:
    https://github.com/RayHY/go-isso/blob/master/internal/app/isso/server/handlers.go#L232
    katsusan
        19
    katsusan  
       2019-01-29 18:37:42 +08:00
    stackoverflow 上看到一种方法:

    对承载 Unmarsha 结果的对象设定一个不可能的默认值。

    ```
    var jsonBlob = []byte(`[
    {"Name": "Platypus", "Order": "Monotremata"}
    ]`)

    type Animal struct {
    Name string
    Order string
    ID
    int
    }

    animals := &Animal{ID: -9999}
    err := json.Unmarshal(jsonBlob, animals)
    if err != nil {
    fmt.Println("error:", err)
    }
    fmt.Printf("%+v", animals)
    ```

    原文: https://stackoverflow.com/questions/39160807/default-value-golang-struct-using-encoding-json
    rayhy
        20
    rayhy  
       2019-01-29 18:41:14 +08:00
    @rayhy
    其实使用一个新的 struct 代替原来的类型是最实在的方法了,不 hack,很通用,最关键是这些类型也可以在 sql 库里面使用,用来区分 0 值和不存在。

    简单的说就是这个: https://godoc.org/gopkg.in/guregu/null.v3#Int.UnmarshalJSON

    UnmarshalJSON implements json.Unmarshaler. It supports number and null input. 0 will not be considered a null Int. It also supports unmarshalling a sql.NullInt64.
    est
        21
    est  
       2019-01-29 19:02:35 +08:00
    每次有人说强类型语言方便,我就想举这个例子。
    kimown
        22
    kimown  
       2019-01-29 19:13:07 +08:00 via Android   ❤️ 1
    简直了,go 一天到晚都在解决接受数据是什么的问题?
    WilliamYang
        23
    WilliamYang  
       2019-01-29 19:17:24 +08:00
    我也想知道目前最好的解决办法, 我之前用了另外一个字段来标记是否有传入值, 觉得用指针好像不太优雅
    janxin
        24
    janxin  
       2019-01-29 23:12:20 +08:00 via iPad
    @kimown 强类型语言都有这个问题吧…
    ck65
        25
    ck65  
       2019-01-30 00:37:04 +08:00
    指针 +1
    reus
        26
    reus  
       2019-01-30 08:34:47 +08:00
    @est
    @kimown

    都说了用指针了,传了 null,指针就是 nil,传了数值,就是指向数值的指针

    能不能学习一下再来黑?
    justfly
        27
    justfly  
       2019-01-30 10:21:22 +08:00
    @123string POST body 中的数据一般不外乎 multipart form,url 编码的数据 和 json,这几类都可以在拿到 request body 之后进行解析,前两个 golang 标准库中本身就有,其实现就是个 map,json 解析到 map 直接 json.Unmarshal 就可以,文档里面有示例。
    yimiao
        28
    yimiao  
       2019-01-30 15:03:51 +08:00
    如果使用 新的 struct int*来接受数据,然后又要做一道赋值转化到另外一个 struct int ?好像很多 orm 不支持 int*是主键的额?
    soulsxd
        29
    soulsxd  
       2019-01-30 16:16:07 +08:00
    解析前赋值其它值
    dongisking
        30
    dongisking  
       2019-01-30 17:10:46 +08:00
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5485 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 03:36 · PVG 11:36 · LAX 19:36 · JFK 22:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.