I wanted to try sorting a slice of structs by the field's json tag, here is what I ended up having, in case it helps anyone:
package main
import (
"fmt"
"reflect"
"sort"
)
func sortBy(jsonField string, arr []num) {
if len(arr) < 1 {
return
}
// first we find the field based on the json tag
valueType := reflect.TypeOf(arr[0])
var field reflect.StructField
for i := 0; i < valueType.NumField(); i++ {
field = valueType.Field(i)
if field.Tag.Get("json") == jsonField {
break
}
}
// then we sort based on the type of the field
sort.Slice(arr, func(i, j int) bool {
v1 := reflect.ValueOf(arr[i]).FieldByName(field.Name)
v2 := reflect.ValueOf(arr[j]).FieldByName(field.Name)
switch field.Type.Name() {
case "int":
return int(v1.Int()) < int(v2.Int())
case "string":
return v1.String() < v2.String()
case "bool":
return !v1.Bool() // return small numbers first
default:
return false // return unmodified
}
})
fmt.Printf("\nsort by %s:\n", jsonField)
prettyPrint(arr)
}
func prettyPrint(arr []num) {
for _, v := range arr {
fmt.Printf("%+v\n", v)
}
}
type num struct {
Id int `json:"id"`
Name string `json:"name"`
Big bool `json:"big"`
}
func main() {
userArray := []num{
{1, "one", false},
{5, "five", false},
{40, "fourty", true},
{9, "nine", false},
{60, "sixty", true},
}
fmt.Println("original:")
prettyPrint(userArray)
sortBy("id", userArray[:])
sortBy("name", userArray[:])
sortBy("big", userArray[:])
}
original:
{Id:1 Name:one Big:false}
{Id:5 Name:five Big:false}
{Id:40 Name:fourty Big:true}
{Id:9 Name:nine Big:false}
{Id:60 Name:sixty Big:true}
sort by id
{Id:1 Name:one Big:false}
{Id:5 Name:five Big:false}
{Id:9 Name:nine Big:false}
{Id:40 Name:fourty Big:true}
{Id:60 Name:sixty Big:true}
sort by name
{Id:5 Name:five Big:false}
{Id:40 Name:fourty Big:true}
{Id:9 Name:nine Big:false}
{Id:1 Name:one Big:false}
{Id:60 Name:sixty Big:true}
sort by big
{Id:1 Name:one Big:false}
{Id:9 Name:nine Big:false}
{Id:5 Name:five Big:false}
{Id:40 Name:fourty Big:true}
{Id:60 Name:sixty Big:true}