V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
guonaihong
V2EX  ›  程序员

golang 1.13 Value.IsZero 值得期待的地方

  •  
  •   guonaihong ·
    guonaihong · 2019-10-11 09:34:20 +08:00 · 3117 次点击
    这是一个创建于 1630 天前的主题,其中的信息可能已经有所发展或是发生改变。

    随着 go1.13 发布,reflect 包里新加了 IsZero 函数。随着该函数的加入,可能会解决一个遗留问题。

    go version

    go version go1.13.1 linux/amd64

    问题请看

    在 json 编码里面,如果打上 omitempty,值为空是不会输出内容的

    package main
    
    import (
        "fmt"
        //"reflect"
        "encoding/json"
        "time"
    )
    
    type test struct {
        Tm time.Time `json:"tm,omitempty"`
        X  int       `json:"x,omitempty"`
        Y  int 
    }
    
    func main() {
        all, err := json.Marshal(test{})
        fmt.Printf("%s, %v\n", all, err)
    }
    
    /*
    输出 {"tm":"0001-01-01T00:00:00Z","Y":0}, <nil>
    */
    

    这什么情况? omitempty 没用 难道对结构体使用没有作用,tm 里面竟然有东西?我们加个自定义结构体再看下(time.Time 的实现方式是结构体)。

    package main
    
    import (
        "encoding/json"
        "fmt"
        //"reflect"
        "time"
    )
    
    type mystruct struct {
        I int `json:"i,omitempty"`
        J int `json:"j,omitempty"`
    }
    
    type test struct {
        Tm time.Time `json:"tm,omitempty"`
        X  int       `json:"x,omitempty"`
        Y  int
    
        M mystruct `json:"m,omitempty"`
    }
    
    func main() {
        all, err := json.Marshal(test{})
        fmt.Printf("%s, %v\n", all, err)
    
        //fmt.Printf("%t\n", reflect.ValueOf(test{}).IsZero())
    }
    
    /*
    {"tm":"0001-01-01T00:00:00Z","Y":0,"m":{}}, <nil>
    */
    

    自定义结构体声明的 m 字段有值,在这个版本里面 omitempty 遇到结构体还是没起作用。

    回到正题

    随着 Value.IsZero 的加入,在未来的 go 版本上面的问题有可能得到解决。打开上面代码的注释, 会发现 reflect.ValueOf(test{}).IsZero()输出为 true。在 json 编码器检测到 omitempty 字段,再调用下 reflect.ValueOf(xxx).IsZero(),忽略这个字段就行。

    在现有的版本如何解决这个问题

    • 用指针

    github

    https://github.com/guonaihong/gout

    4 条回复    2019-10-11 13:16:03 +08:00
    Reficul
        1
    Reficul  
       2019-10-11 11:05:01 +08:00
    诶,辣么要是这个字段的值就是 0 咋办: 即预期希望输出 {"Y":0}。

    如果 JSON 标准库加上这个 feature,是不是会破坏已有的兼容,应该这样的改动不会进吧。

    所以。。。。老老实实使用指针吧。。。。
    guonaihong
        2
    guonaihong  
    OP
       2019-10-11 12:41:14 +08:00
    @Reficul 未来 go 如果通过这个 feature。可以通过 omitempty 字段控制,加了才忽略。用指针还要判断指针为空的情况,用起来还是挺累的。

    if p == nil {
    return
    }
    Reficul
        3
    Reficul  
       2019-10-11 12:57:59 +08:00
    @guonaihong

    Y= nil 的时候忽略,和 Y = 0 (默认值)的时候忽略是不一样的呀。

    比如你输出的这个 JSON 里希望这个值在某种场景下是不返回的,则忽略;但是在某种场景下需要返回,但是值就是 0 则不希望忽略。
    guonaihong
        4
    guonaihong  
    OP
       2019-10-11 13:16:03 +08:00
    @Reficul 恩,这个需求只能用指针。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2681 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 15:46 · PVG 23:46 · LAX 08:46 · JFK 11:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.