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

时间:2018-04-06 09:49:07

标签: go formatting

考虑以下代码:

O(C*n^2)

是否有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} } 格式说明符只能打印非零值的字段?

例如,使用上面的代码,我怎么才能打印

fmt

因为{c:true} a == ""

1 个答案:

答案 0 :(得分:3)

没有内置格式动词导致零值被省略。

以下是一些选项。

fmt.Stringer

您可以通过实施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)
}

输出:

{a:"foo"}

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

反射

你可以使用反射来构建适用于任何结构的东西,但它可能比它的价值更麻烦。示例省略。

JSON

另一个替代方法是将其封送到JSON,JSON处理反射部分并支持省略零值。例如:

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)
    }
}

输出:

{"A":"foo"}

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

带有未导出字段的JSON

如果您希望原始结构保持原样;您可以使用匿名结构定义自定义编组器。但是请注意,然后在MarshalJSON方法中复制了struct格式,这增加了一些复杂性:

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)
    }
}

输出:

{"a":"foo"}

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

带有未导出字段的JSON + fmt.Stringer

如果您愿意,可以再次实施fmt.Stringer,其中fmt.Printf和朋友会选择:

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)
}

输出:

{"a":"foo"}

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