一、反射 Go基础教程可看 
Go 系列教程 — 34. 反射 
反射 
Go 语言反射的实现原理 
这里记下用的部分
1.1 reflect.Value reflect.Value 可以表示一个任意类型的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package  mainimport  (	"fmt"  	"reflect"  ) type  User struct  {	Name string  	Age int  } func  main () 	u := User{"张三" , 56 } 	v := reflect.ValueOf(u) 	fmt.Println(v) } 
1.2 reflect.Kind 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package  mainimport  (	"fmt"  	"reflect"  ) type  User struct  {	Name string  	Age int  } func  main () 	u := User{"张三" , 56 } 	t := reflect.TypeOf(u) 	k := t.Kind() 	fmt.Println(t) 	fmt.Println(k) } 
1.3 反射字段 想要利用反射拿到结构体的字段,然后对其操作,需要这个字段是可访问的,也就是首字母大写
reflect.Indirect()函数用于获取传入参数指向的值
1 2 3 4 5 6 func  Indirect (v Value) 	if  v.Kind() != Ptr { 		return  v 	} 	return  v.Elem() } 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package  mainimport  (	"fmt"  	"reflect"  ) type  User struct  {	Name string  	Age int  } func  main () 	u := User{"张三" , 56 } 	indirect := reflect.Indirect(reflect.ValueOf(&u)).FieldByName("Age" ) 	fmt.Println(indirect) } 
1 2 3 func  Indirect (v Value) func  (v Value) 
这二个长的很像的兄弟有什么区别
*Elem  returns the value that the interface v contains or that the pointer v points to. It panics if v’s Kind is not Interface or Ptr. It returns the zero Value if v is nil.*
*Indirect  returns the value that v points to. If v is a nil pointer, Indirect returns a zero Value. If v is not a pointer, Indirect returns v.*
如果reflect.Value是一个指针, 那么v.Elem()等价于reflect.Indirect(v) 
如果不是指针
如果是interface ,那么reflect.Indirect(v)返回原值,而v.Elem()返回interface中包含的值 
如果是其它值, v.Elem()会panic,而reflect.Indirect(v)返回原值 
 
 
 
 
二、排序 2.1 场景 给定特定字段字符串对结构体切片进行排序,如下
sortutil.DescByField 按照User结构体中的Age字段从大到小对切片排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package  mainimport  (	"fmt"  	"reflect"  ) type  User struct  {	Name string  	Age int  } func  main () 	userSlice := []User{{"张三" , 56 }, {"李四" , 13 }, {"王五" , 24 }} 	sortutil.DescByField(userSlice, "Age" ) } 
2.2 sort.Slice Go中有个sort.Slice 方法可以对结构体切片排序
1 2 3 sort.Slice(userSlice , func (i, j int ) bool  { 		return  userSlice [i].Age > userSlice [j].Age }) 
但是这样得配合switch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 userSlice := []User{{"张三" , 56 }, {"李四" , 13 }, {"王五" , 24 }} field := "Name"  switch  field{	case  "Age" : 		sort.Slice(userSlice , func (i, j int ) bool  { 			return  userSlice [i].Age > userSlice [j].Age 		}) 	case  "Name" : 		sort.Slice(userSlice , func (i, j int ) bool  { 			return  userSlice [i].Name > userSlice [j].Name 		}) } for  _, user := range  userSlice{	fmt.Println(user) } 
2.2 SortWrapper sort - The Go Programming Language 
使用SortWrapper优雅地实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package  mainimport  (	"fmt"  	"sort"  ) type  User struct  {	Name string  	Age int  } type  Users []Userfunc  (s Users) int       { return  len (s) }func  (s Users) int ) { s[i], s[j] = s[j], s[i] }type  ByName struct { Users }func  (u ByName) int ) bool  { return  u.Users[i].Name < u.Users[j].Name }type  ByAge struct { Users }func  (u ByAge) int ) bool  { return  u.Users[i].Age < u.Users[j].Age}func  main () 	userSlice := []User{{"张三" , 56 }, {"李四" , 13 }, {"王五" , 24 }} 	sort.Sort(ByAge{userSlice}) 	for  _, user := range  userSlice{ 		fmt.Println(user) 	} } 
然后配上map可以曲线救国
1 2 3 4 5 6 m := make (map [string ]sort.Interface) m["Age" ] = ByAge{userSlice} m["Name" ] = ByName{userSlice} field := "Age"  sort.Sort(m[field]) 
2.3 反射 使用反射排序n多年前就有大佬实现了,只不过是停止更新了,不过还是可以用的,使用起来挺简单的,按照给的示例模仿就ok
主要是因为涉及到内存分配以及后续的GC以及reflect实现里面有大量的枚举,也就是for循环,比如类型之类的。
patrickmn/sortutil 
How to sort an array of struct by field? 
拿2.1那个代码来讲
1 sortutil.DescByField(userSlice, "Age" ) 
该方法主要是通过反射按照给定的字段名从给定的切片中拿到关于该字段的列表
然后判断类型
stringDescending 是为了实现自定义的大于比较规则。不比已知的int,string等类型,对于未知类型Golang也不知道如何比较大小
然后对所得到的反射列表排序
这里会根据数组的特点选择是快排还是堆排