dongzantai7570 2018-04-06 09:49 采纳率: 0%
浏览 76
已采纳

fmt格式说明符仅打印具有非零值的字段

Consider this code:

package main

import (
    "fmt"
)

type myStruct struct {
    a string
    b int
    c bool
}

func main() {

    s := myStruct{
        c: true,
    }
    fmt.Printf("%v", s)
    // print { 0 true}
    fmt.Printf("%+v", s)
    // print {a: b:0 c:true}
}

Is there a fmt format specifier to print only fields with non-zero value?

For example, with the code above, how can I print only

{c:true} 

because a == "" and b == 0?

  • 写回答

1条回答 默认 最新

  • dsshsta97935 2018-04-06 10:31
    关注

    There is no built-in format verb that causes zero values to be omitted.

    Here are some options.

    fmt.Stringer

    You can hard-code the string format for your type by implementing fmt.Stringer:

    package main
    
    import (
        "fmt"
        "strings"
    )
    
    type myStruct struct {
        a string
        b int
        c bool
    }
    
    func (s myStruct) String() string {
        var fields []string
    
        if s.a != "" {
            fields = append(fields, fmt.Sprintf("a:%q", s.a))
        }
    
        if s.b != 0 {
            fields = append(fields, fmt.Sprintf("b:%d", s.b))
        }
    
        if s.c {
            fields = append(fields, fmt.Sprintf("c:%t", s.c))
        }
    
        return fmt.Sprintf("{%s}", strings.Join(fields, ","))
    }
    
    func main() {
        s := myStruct{a: "foo"}
    
        fmt.Println(s)
    }
    

    Output:

    {a:"foo"}
    

    https://play.golang.org/p/Dw7F4Ua0Eyq


    Reflection

    You can use reflection to build something that will work with any struct, but it is perhaps more hassle than it is worth. Example omitted.


    JSON

    Another alternative is to marshal it to JSON, which handles the reflection part and has support for omitting zero values. Example:

    package main
    
    import (
        "encoding/json"
        "log"
        "os"
    )
    
    type myStruct struct {
        A string `json:",omitempty"`
        B int    `json:",omitempty"`
        C bool   `json:",omitempty"`
    }
    
    func main() {
        s := myStruct{A: "foo"}
    
        if err := json.NewEncoder(os.Stdout).Encode(s); err != nil {
            log.Fatal(err)
        }
    }
    

    Output:

    {"A":"foo"}
    

    https://play.golang.org/p/NcckEBNdnW6


    JSON with unexported fields

    If you prefer to keep the original struct as-is; you can define a custom marshaller with an anonymous struct. Note however that the struct format is then duplicated in the MarshalJSON method which adds a bit of complexity:

    package main
    
    import (
        "encoding/json"
        "log"
        "os"
    )
    
    type myStruct struct {
        a string
        b int
        c bool
    }
    
    func (s myStruct) MarshalJSON() ([]byte, error) {
        return json.Marshal(
            struct {
                A string `json:"a,omitempty"`
                B int    `json:"b,omitempty"`
                C bool   `json:"c,omitempty"`
            }{
                A: s.a,
                B: s.b,
                C: s.c,
            },
        )
    }
    
    func main() {
        s := myStruct{a: "foo"}
    
        if err := json.NewEncoder(os.Stdout).Encode(s); err != nil {
            log.Fatal(err)
        }
    }
    

    Output:

    {"a":"foo"}
    

    https://play.golang.org/p/qsCKUNeFLpw


    JSON with unexported fields + fmt.Stringer

    If you want, you can again implement fmt.Stringer, which fmt.Printf and friends will pick up:

    package main
    
    import (
        "encoding/json"
        "fmt"
    )
    
    type myStruct struct {
        a string
        b int
        c bool
    }
    
    func (s myStruct) MarshalJSON() ([]byte, error) {
        return json.Marshal(
            struct {
                A string `json:"a,omitempty"`
                B int    `json:"b,omitempty"`
                C bool   `json:"c,omitempty"`
            }{
                A: s.a,
                B: s.b,
                C: s.c,
            },
        )
    }
    
    func (s myStruct) String() string {
        j, err := json.Marshal(s)
        if err != nil {
            return ""
        }
        return string(j)
    }
    
    func main() {
        s := myStruct{a: "foo"}
    
        fmt.Println(s)
    }
    

    Output:

    {"a":"foo"}
    

    https://play.golang.org/p/TPDoLOTAVJo

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥60 Matlab联合CRUISE仿真编译dll文件报错
  • ¥15 脱敏项目合作,ner需求合作
  • ¥15 脱敏项目合作,ner需求合作
  • ¥30 Matlab打开默认名称带有/的光谱数据
  • ¥50 easyExcel模板 动态单元格合并列
  • ¥15 res.rows如何取值使用
  • ¥15 在odoo17开发环境中,怎么实现库存管理系统,或独立模块设计与AGV小车对接?开发方面应如何设计和开发?请详细解释MES或WMS在与AGV小车对接时需完成的设计和开发
  • ¥15 CSP算法实现EEG特征提取,哪一步错了?
  • ¥15 游戏盾如何溯源服务器真实ip?需要30个字。后面的字是凑数的
  • ¥15 vue3前端取消收藏的不会引用collectId