dongmingxiang0312 2015-06-18 10:58
浏览 58
已采纳

如何按字母顺序对结构字段排序

How could I get an output of struct, sorted by fields?

type T struct {
    B int
    A int
}

t := &T{B: 2, A: 1}

doSomething(t)

fmt.Println(t)  // &{1 2} --> Sorted by fields
  • 写回答

2条回答 默认 最新

  • douqiang6448 2015-06-18 12:15
    关注

    A struct is an ordered collection of fields. The fmt package uses reflection to get the fields and values of a struct value, and generates output in the order in which they were defined.

    So the simplest solution would be to declare your type where you already have your fields arranged in alphabetical order:

    type T struct {
        A int
        B int
    }
    

    If you can't modify the order of fields (e.g. memory layout is important), you can implement the Stringer interface by specifying a String() method for your struct type:

    func (t T) String() string {
        return fmt.Sprintf("{%d %d}", t.A, t.B)
    }
    

    The fmt package checks if the passed value implements Stringer, and if it does, calls its String() method to generate the output.

    Cons of this solution is that this is not flexible (e.g. if you add a new field, you have to update the String() method too), also you have to do it for every struct type you want it to work (and you can't define methods for types defined in other packages).

    The completely flexible solution can use reflection. You can get the names of fields, sort them by name, and then iterate over the sorted names and get the field values (by name).

    Pros of this solution is that this works for any struct, and it keeps working without modification even if you add or remove fields from your structs. It also works for fields of any type, not just for int fields.

    Here is an example how to do it (try it on the 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条)

报告相同问题?

悬赏问题

  • ¥20 基于MSP430f5529的MPU6050驱动,求出欧拉角
  • ¥20 Java-Oj-桌布的计算
  • ¥15 powerbuilder中的datawindow数据整合到新的DataWindow
  • ¥20 有人知道这种图怎么画吗?
  • ¥15 pyqt6如何引用qrc文件加载里面的的资源
  • ¥15 安卓JNI项目使用lua上的问题
  • ¥20 RL+GNN解决人员排班问题时梯度消失
  • ¥60 要数控稳压电源测试数据
  • ¥15 能帮我写下这个编程吗
  • ¥15 ikuai客户端l2tp协议链接报终止15信号和无法将p.p.p6转换为我的l2tp线路