Slice のソート
シンプルに型アサーション (Type Assertions) を使います。
type Person struct {
Name string
Age int
}
type People []Person
func (p People) Len() int { return len(p) }
func (p People) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p People) Less(i, j int) bool { return p[i].Age < p[j].Age }
func Sort(v interface{}) interface{} {
s, ok := v.(sort.Interface)
if !ok {
return v
}
sort.Sort(s)
return s
}
func main() {
people := People{{"Bob", 31}, {"John", 42}, {"Michael", 17}, {"Jenny", 26}}
fmt.Println(people) // [{Bob 31} {John 42} {Michael 17} {Jenny 26}]
Sort(people)
fmt.Println(people) // [{Michael 17} {Jenny 26} {Bob 31} {John 42}]
}
interface{}
が sort.Interface
を実装した Slice であると期待できる場合、この方法で十分でしょう。
入れ子になった Slice のソート
入れ子になった Slice もソートしたい場合は、構造体のフィールドと Slice のインデックスを走査します。
func Sort(v interface{}) {
switch values := reflect.ValueOf(v); values.Kind() {
case reflect.Slice:
for i := 0; i < values.Len(); i++ {
if values.Index(i).CanSet() {
Sort(values.Index(i).Interface())
}
}
case reflect.Struct:
for i := 0; i < values.NumField(); i++ {
if values.Field(i).CanSet() {
Sort(values.Field(i).Interface())
}
}
case reflect.Ptr:
Sort(values.Elem().Interface())
}
if s, ok := v.(sort.Interface); ok {
sort.Sort(s)
return
}
switch s := v.(type) {
case []int:
sort.Ints(s)
case []float64:
sort.Float64s(s)
case []string:
sort.Strings(s)
}
}