这个资料真的难找,搜了一圈,基本都是一样的,都是讲怎么通过反射改变slice中的值,关于自定义字段排序的资料缺是一个也没有。
这也难怪,如果不是为了重构一个方法,关于排序复用代码太多,我也不会查找这方面的资料,并通过实践测试,找到了相关的方法。
源码真的是一个非常非常好的参考资料。在找不到相关自定义字段排序的资料下,我翻了一下 sort.Slice
相关的源码,确定了如果要用反射排序,则需要使用 relfect.ValueOf
方法获取需要排序的内容,如下
// Slice sorts the provided slice given the provided less function.
//
// The sort is not guaranteed to be stable. For a stable sort, use
// SliceStable.
//
// The function panics if the provided interface is not a slice.
func Slice(slice interface{}, less func(i, j int) bool) {
rv := reflectValueOf(slice)
swap := reflectSwapper(slice)
length := rv.Len()
quickSort_func(lessSwap{less, swap}, 0, length, maxDepth(length))
}
并通过资料以及尝试,确定 reflect.Valueof.Index
方法可以获取反射内容的相关值,最终得到通过反射来自定义字段排序的结论代码,示例如下:
代码:
type Str struct {
A string
V int
}
func TestBindParams(t *testing.T) {
var tt = []Str{{A: "test A", V: 2}, {A: "test b", V: 1}, {A: "test c", V: -1}}
f := "V"
sort.Slice(tt, func(i, j int) bool {
tmp := reflect.ValueOf(tt)
// 指针与结构体获取反射字段值的用法不一样
if tmp.Type().Elem().Kind() == reflect.Ptr {
return tmp.Index(i).Elem().FieldByName(f).Int() < tmp.Index(j).Elem().FieldByName(f).Int()
}
return tmp.Index(i).FieldByName(f).Int() < tmp.Index(j).FieldByName(f).Int()
})
t.Log(tt)
}
输出:
=== RUN TestBindParams
TestBindParams: http_test.go:153: [{test c -1} {test b 1} {test A 2}]
--- PASS: TestBindParams (0.00s)
PASS
Process finished with exit code 0