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 關注
- 176 瀏覽
添加回答
舉報