首页 > 解决方案 > 使用分隔符打印结构中的字段列表

问题描述

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

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
}

标签: stringgostruct

解决方案


包的动词不支持该确切格式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上尝试一下。


推荐阅读