我如何得到struct的输出,按字段排序?
type T struct {
B int
A int
}
t := &T{B: 2, A: 1}
doSomething(t)
fmt.Println(t) // &{1 2} --> Sorted by fields
答案 0 :(得分:5)
struct
是有序字段集合。 fmt
包使用反射来获取struct
值的字段和值,并按照定义它们的顺序生成输出。
因此,最简单的解决方案是声明您的字段已按字母顺序排列:
type T struct {
A int
B int
}
如果您无法修改字段的顺序(例如,内存布局很重要),您可以通过为结构类型指定String()
方法来实现Stringer
接口:
func (t T) String() string {
return fmt.Sprintf("{%d %d}", t.A, t.B)
}
fmt
包检查传递的值是否实现Stringer
,如果是,则调用其String()
方法生成输出。
此解决方案的缺点是这不灵活(例如,如果添加新字段,您还必须更新String()
方法),您还必须为每个struct
类型执行此操作你希望它工作(你不能为其他包中定义的类型定义方法)。
完全灵活的解决方案可以使用反射。您可以获取字段的名称,按名称对它们进行排序,然后迭代排序的名称并获取字段值(按名称)。
此解决方案的优点在于,这适用于任何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()
}
答案 1 :(得分:2)
让T
实现Stringer接口(请参阅包fmt),然后先打印A orb B.
顺便说一句。这是一个愚蠢的想法。