项目地址:https://github.com/Mustenaka/Go-simpleSort

改进的Golang排序工具

本工程主要是go在1.18 Bate1版本之前没有引入范型概念,每一次使用Sort排序都要声明一堆东西,想要实现类似其他语言那样的任意排序而构件的,通过反射实现了自定义输入的数据,然后声明需要排序的资源,进行自动排序,随着Go的版本逐步深入

代码:

package simplesort

import (
	"fmt"
	"reflect"
	"sort"

	"github.com/Mustenaka/Go-simpleSort/sortConfig"
)

type SortBy []interface{}

func (a SortBy) Len() int      { return len(a) }
func (a SortBy) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a SortBy) Less(i, j int) bool {
	// Get Sort index
	sortIndex := sortConfig.GetInstance().GetIndex()

	// 定位比较字段
	fieldValue1 := reflect.ValueOf(a[i]).Field(sortIndex)
	fieldValue2 := reflect.ValueOf(a[j]).Field(sortIndex)

	// 断言类型
	switch fieldValue1.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return fieldValue1.Int() < fieldValue2.Int()
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return fieldValue1.Uint() < fieldValue2.Uint()
	case reflect.Float32, reflect.Float64:
		return fieldValue1.Float() < fieldValue2.Float()
	case reflect.String:
		return fieldValue1.String() < fieldValue2.String()
	default:
		panic("unsupported kind")
	}
}

// @title Simplesort
// @description simplified non-generic sort method.
// @param data interface{} "Data to be sorted."
// @param filedName string "sorted index field name."
// @param order bool "oder or reverse order"
// @return interface{}, error "sort results, nil if no error."
func Simplesort(args interface{}, filedName string, order bool) ([]interface{}, error) {
	// 输出数据
	fmt.Println("input: ", args)

	// interface{} convert to []interface{}
	var interfaceSlice []interface{}

	// 判断类型
	if reflect.TypeOf(args).Kind() != reflect.Slice {
		panic("input need slice kind")
	}

	// 输出类型信息
	fmt.Println("args typeof kind: " + reflect.TypeOf(args).Kind().String())

	// 定位目标字段在结构体中的索引
	var index int = 0

	// 切片处理
	s := reflect.ValueOf(args)
	for i := 0; i < s.Len(); i++ {
		ele := s.Index(i)
		t := ele.Type()

		interfaceSlice = append(interfaceSlice, ele.Interface())

		// 检查需要排序字段是否包含在结构体中
		var isExist bool = false
		for ii := 0; ii < ele.NumField(); ii++ {
			// fmt.Printf("name: %s, type: %s, value: %v\n",
			// 	t.Field(ii).Name,
			// 	ele.Field(ii).Type(),
			// 	ele.Field(ii))
			if t.Field(ii).Name == filedName {
				isExist = true
				index = ii
			}
		}

		// 未找到需要排序的字段,抛出错误
		if !isExist {
			// panic("not found filed: " + filedName)
			return nil, fmt.Errorf("not found filed: %s", filedName)
		}
	}

	// 处理完成,初始化排序的配置 - 用单例的方式注入Less方法
	sortConfig.CreateInstance(index, filedName, order)

	// 对结构体数组进行排序
	sort.Sort(SortBy(interfaceSlice))

	// 输出数据
	fmt.Println("output: ", interfaceSlice)
	return interfaceSlice, nil
}

// @title SimplesortStable
// @description reflect test
func FunctionTest(data interface{}) {
	getValue := reflect.ValueOf(data) // Value of v
	if getValue.Kind() != reflect.Slice {
		panic("need slice kind")
	}

	l := getValue.Len()
	for i := 0; i < l; i++ {
		value := getValue.Index(i) // Value of item
		typel := value.Type()      // Type of item
		if typel.Kind() != reflect.Struct {
			panic("need struct kind")
		}

		fmt.Printf("type-kind: %s, type-name: %s, value: %v\n", typel.Kind(), typel.Name(), value.Interface())

		num := value.NumField()
		for j := 0; j < num; j++ {
			fmt.Printf("name: %s, type: %s, value: %v\n",
				typel.Field(j).Name,
				value.Field(j).Type(),
				value.Field(j))
		}
	}
}

// 单例模式测试
func SinTest(filedName string) {
	sortConfig.CreateInstance(2, filedName, true)

	fmt.Println("instance: ", sortConfig.GetInstance().GetIndex())
	fmt.Println("instance: ", sortConfig.GetInstance().GetName())
	fmt.Println("instance: ", sortConfig.GetInstance().GetOrder())
}
分类: Go

1 条评论

golang 自定义结构体排序 – 木十的博客 · 2022年7月20日 下午9:59

[…] 改进的Golang排序库-Golang简单排序 […]

回复 golang 自定义结构体排序 – 木十的博客 取消回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用 * 标注