Go语言如何按前端传入的JSON标签对应动态字段对结构体数组排序
Go 结构体数组按前端传递的动态JSON标签排序实现
Go为静态强类型语言,无法直接通过字符串动态指定结构体字段进行比较,以下提供两种可直接落地的实现方案:
方案一:字段比较映射表(推荐,无反射开销,性能最优)
适合结构体字段数量较少的场景,直接预先建立JSON标签和对应比较逻辑的映射关系即可:
// 1. 先获取前端传递的排序字段 sortField := agnutil.GetQueryParamString(<json tag>, "sort", 0, "name") // 可选扩展:如果需要支持升降序可以再加一个排序方向参数,比如 sortOrder := agnutil.GetQueryParamString(..., "order", 0, "asc") // 2. 建立JSON标签到比较逻辑的映射表 compareMap := map[string]func(i, j int) bool{ "name": func(i, j int) bool { return UserArray[i].Name < UserArray[j].Name }, "age": func(i, j int) bool { return UserArray[i].Age < UserArray[j].Age }, "status": func(i, j int) bool { return UserArray[i].Status < UserArray[j].Status }, "type": func(i, j int) bool { return UserArray[i].Type < UserArray[j].Type }, } // 3. 校验排序字段合法性,不存在则使用默认排序逻辑 compareFunc, ok := compareMap[sortField] if !ok { compareFunc = compareMap["name"] // 默认按name排序 } // 4. 执行排序 sort.Slice(UserArray, compareFunc)
如果需要支持升降序,只需要根据排序方向参数,对返回的布尔值取反即可。
方案二:反射实现(适合字段较多的场景,无需重复写映射逻辑,性能略低)
如果结构体字段特别多,写映射表太繁琐,可以通过反射动态解析结构体的JSON标签,匹配对应字段后取值比较:
import ( "reflect" "sort" "strings" ) // 1. 获取排序字段 sortField := agnutil.GetQueryParamString(<json tag>, "sort", 0, "name") // 2. 执行动态排序 sort.Slice(UserArray, func(i, j int) bool { // 分别获取两个元素的反射值 vI := reflect.ValueOf(UserArray[i]) vJ := reflect.ValueOf(UserArray[j]) // 遍历结构体所有字段匹配JSON标签 for k := 0; k < vI.Type().NumField(); k++ { field := vI.Type().Field(k) // 解析json标签,去掉额外的omitempty等参数 tagValue := strings.Split(field.Tag.Get("json"), ",")[0] if tagValue == sortField { // 根据字段类型执行对应比较 switch field.Type.Kind() { case reflect.Int: return vI.Field(k).Int() < vJ.Field(k).Int() case reflect.String: return vI.Field(k).String() < vJ.Field(k).String() // 可以按需扩展其他类型的比较逻辑 default: return false } } } // 未匹配到字段时默认按name排序 return UserArray[i].Name < UserArray[j].Name })
注意:反射方案每次排序都要遍历字段和类型判断,性能远低于映射表方案,高并发场景优先选择方案一。
内容的提问来源于stack exchange,提问作者Ibjas Mohamed
相关产品推荐
相关产品推荐

