【问题标题】:Print list of fields in struct with delimiter使用分隔符打印结构中的字段列表
【发布时间】:2019-12-09 10:54:03
【问题描述】:

我有一个包含三个字段的类型

type Person struct {
    FirstName string
    LastName  string
    Age       int
}

创建一个实例并使用默认的fmt.Sprint() 返回{John Smith 45}。但是对于我的用例,我需要一个格式为John, Smith, 45 的字符串。没有被花括号包围的逗号分隔列表。有没有比以下更可重用和有效的方法:

fmt.Sprintf("%s, %s, %d", x.FirstName, x.LastName, x.Age)

我会将此方法与其他类型一起使用,我更喜欢通用方法,而不是为我使用的每种类型输入格式:

func asFields(data interface{}) string {
    // TODO logic here
}

【问题讨论】:

    标签: string go struct


    【解决方案1】:

    fmt 包的动词不支持该确切格式。

    最接近的应该是

    s := fmt.Sprintf("%#v", p)
    

    生成如下字符串:

    main.Person{FirstName:"John", LastName:"Smith", Age:45}
    

    如果您确实需要您在问题中发布的内容,您可以使用反射来迭代字段并构建如下结果:

    func asFields(data interface{}) string {
        v := reflect.ValueOf(data)
        b := &strings.Builder{}
        for i := 0; i < v.NumField(); i++ {
            if i > 0 {
                b.WriteString(", ")
            }
            b.WriteString(fmt.Sprint(v.Field(i).Interface()))
        }
        return b.String()
    }
    

    这确实给出了:

    John, Smith, 45
    

    尝试Go Playground 上的示例。

    请注意,这个asFields() 函数当然可以处理所有结构类型,而不仅仅是您的Person。当然需要调整来处理指针和结构体。

    另请注意,除了fmt.Sprint(),您还可以使用fmt.Fprint() 指向我们正在组装字符串的缓冲区:

    func asFields(data interface{}) string {
        v := reflect.ValueOf(data)
        b := &strings.Builder{}
        for i := 0; i < v.NumField(); i++ {
            if i > 0 {
                b.WriteString(", ")
            }
            fmt.Fprint(b, v.Field(i).Interface())
        }
        return b.String()
    }
    

    这当然会给出相同的结果(可能会更快,也可能不会更快,对它进行基准测试)。在Go Playground 上试试吧。

    【讨论】:

    • 另请注意,它会产生反射成本,并且会比 OP 已经使用的静态解决方案慢。
    【解决方案2】:

    我们可以使用这种方法吗,但它只适用于Person type struct

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

    package main
    
    import (
        "fmt"
    )
    
    type Person struct {
        FirstName string
        LastName  string
        Age       int
    }
    
    func (p Person) String() string {
        return fmt.Sprintf("%s, %s, %d", p.FirstName, p.LastName, p.Age)
    }
    
    func main() {
        p := Person{FirstName: "John",LastName: "Doe", Age: 25}
        fmt.Printf("%v", p)
    }
    

    输出:

    John, Doe, 25
    

    类似的问题: ToString() function in Go

    【讨论】:

    • 接口的力量。这比使用反射更容易和更清洁。
    猜你喜欢
    • 1970-01-01
    • 2015-07-17
    • 2011-05-02
    • 2015-02-04
    • 1970-01-01
    • 2016-03-07
    • 1970-01-01
    • 2011-01-24
    • 2020-08-26
    相关资源
    最近更新 更多