使用分隔符打印struct中的字段列表

时间:2019-12-09 10:54:03

标签: string go struct

我有一个带有三个字段的类型

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
}

2 个答案:

答案 0 :(得分:5)

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上尝试一下。

答案 1 :(得分:1)

我们可以使用这种方法,但是它仅适用于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