2 回答
TA贡献1817条经验 获得超14个赞
Astruct是字段的有序集合。该fmt包使用反射来获取值的字段和值struct,并按照定义的顺序生成输出。
因此,最简单的解决方案是声明您的类型,其中您已经按字母顺序排列了您的字段:
type T struct {
A int
B int
}
如果你不能修改字段的顺序(例如内存布局很重要),你可以Stringer通过String()为你的结构类型指定一个方法来实现接口:
func (t T) String() string {
return fmt.Sprintf("{%d %d}", t.A, t.B)
}
该fmt包检查传递的值是否实现Stringer,如果实现,则调用其String()方法来生成输出。
该解决方案的缺点是这不灵活(例如,如果您添加一个新字段,您也必须更新该String()方法),而且您还必须为struct您希望它工作的每种类型都这样做(并且您不能定义方法)对于其他包中定义的类型)。
完全灵活的解决方案可以使用反射。您可以获取字段的名称,按名称对其进行排序,然后遍历排序后的名称并获取字段值(按名称)。
该解决方案的优点是它适用于 any struct,并且即使您在结构中添加或删除字段,它也可以继续工作而无需修改。它也适用于任何类型的字段,而不仅仅是int字段。
这是一个如何做到的示例(在Go Playground上尝试):
func printFields(st interface{}) string {
t := reflect.TypeOf(st)
names := make([]string, t.NumField())
for i := range names {
names[i] = t.Field(i).Name
}
sort.Strings(names)
v := reflect.ValueOf(st)
buf := &bytes.Buffer{}
buf.WriteString("{")
for i, name := range names {
val := v.FieldByName(name)
if !val.CanInterface() {
continue
}
if i > 0 {
buf.WriteString(" ")
}
fmt.Fprintf(buf, "%v", val.Interface())
}
buf.WriteString("}")
return buf.String()
}
- 2 回答
- 0 关注
- 160 浏览
添加回答
举报