合规国际互联网加速 OSASE为企业客户提供高速稳定SD-WAN国际加速解决方案。 广告
~~~ package toolutilv3 import ( "encoding/json" "fmt" "reflect" "sort" ) var ToolSlice = toolSliceUtil{} type toolSliceUtil struct{} /* AppendHead 向切片头部追加元素 ChangeInterfaceToSlice 将 []interface{} 类型的切片转换成指定类型的切片 ChangeSliceToInterface 将任意切片类型的切片 转换为 []interface{} 类型 Contains 方法可以检查给定的切片中是否存在某个元素 ConvertSliceToMap 将结构体切片转出[]map[string]interface{} FindDiffVales 找到两个切片中不同的元素,返回两个切片中不同元素组成的切片 FindSameVales 找到两个切片中同同的元素,返回两个切片中相同同元素组成的切片 FindOutVales 从slice1里剔除slice2存在的值 GroupByKey 将[]map[string]interface{}按某个字段分组 MapListKeyToIntSlice 函数从输入的 []map[string]interface{} 类型的切片中提取指定 key 对应的 int 类型数值,并返回一个 []int 类型的切片。 UniqueInterface 函数用于合并多个任意类型的切片并去重 SetNilToDefaultValueByMap 字典中所有键名在 keys 数组中出现过且对应的键值为 nil 的元素改为默认值 defaultValue SetNilToDefaultValueByMapV2 处理nil值,出现在keys的nil设置成[], 其余的nil设置成"" SetNilToDefaultValueBySlice 切片中所有键名在 keys 数组中出现过且对应的键值为 nil 的元素改为默认值 defaultValue SetNilToDefaultValueBySliceV2 处理nil值,出现在keys的nil设置成[], 其余的nil设置成"" SortByKey 函数按照指定的 key 对应的值,对输入的 []map[string]interface{} 类型的切片进行排序。 StringToSlice 将字符串解析为切片类型 StringToSliceInt 将字符串解析为Int切片类型 StringToMap 将字符串解析为字典类型 StringToMapSlice 将字符串解析为切片类型 */ //备注 // AppendHead 向切片头部追加元素 func (s *toolSliceUtil) AppendHead(slice []interface{}, addData interface{}) []interface{} { return append([]interface{}{addData}, slice...) } // ChangeInterfaceToSlice 将 []interface{} 类型的切片转换成指定类型的切片 func (s *toolSliceUtil) ChangeInterfaceToSlice(slice []interface{}, elementType reflect.Type) interface{} { // 创建一个新切片,使用reflect.MakeSlice函数创建 // 第一个参数是要创建的切片类型,使用reflect.SliceOf函数获取 // 第二个参数是要创建的切片长度和容量,这里都设置为输入 slice 的长度 newSlice := reflect.MakeSlice(reflect.SliceOf(elementType), len(slice), len(slice)) // 遍历输入的切片,将其中每个元素转换成指定类型,并设置到新切片中 for i := 0; i < len(slice); i++ { // 使用reflect.ValueOf函数获取当前元素的反射对象 // 然后调用Convert方法将其转换成指定类型,并使用Set方法设置到新切片中 newSlice.Index(i).Set(reflect.ValueOf(slice[i]).Convert(elementType)) } // 返回转换后的新切片,注意需要使用 .Interface() 方法将其转换成 interface{} 类型 return newSlice.Interface() } // ChangeSliceToInterface 将任意切片类型的切片 转换为 []interface{} 类型 func (s *toolSliceUtil) ChangeSliceToInterface(slice interface{}) []interface{} { sliceValue := reflect.ValueOf(slice) if sliceValue.Kind() != reflect.Slice { panic("ToInterfaceSlice only supports slice types") } interfaceSlice := make([]interface{}, sliceValue.Len()) for i := 0; i < sliceValue.Len(); i++ { interfaceSlice[i] = sliceValue.Index(i).Interface() } return interfaceSlice } /* 参数slice是要检查的切片,参数item是要查找的元素 */ // Contains 方法可以检查给定的切片中是否存在某个元素 func (s *toolSliceUtil) Contains(slice interface{}, item interface{}) bool { // 使用反射获取slice的值 v := reflect.ValueOf(slice) // 检查v的类型是否为切片类型 if v.Kind() != reflect.Slice { return false } // 获取slice元素的类型 elemType := v.Type().Elem() // 如果元素类型不可比较,则无法使用该方法进行查找 if !elemType.Comparable() { return false } // 遍历整个切片 for i := 0; i < v.Len(); i++ { // 使用DeepEqual函数比较切片中的元素和要查找的元素 if reflect.DeepEqual(item, v.Index(i).Interface()) { return true } } // 如果循环结束仍未找到匹配项,则返回false return false } /* 该函数接受一个参数 slice,可以接受任何类型的切片结构体。 在函数内部,我们首先使用反射获取传入参数的值和类型,然后遍历每个结构体实例,将其转换为 map[string]interface{} 类型,并添加到结果切片中。最后,返回转换好的切片。 如果传入的参数不是切片类型或者切片元素不是结构体类型,函数会返回一个错误 not a slice 或者 not a struct。这可以防止代码在运行时出现崩溃或者异常情况。 */ // ConvertSliceToMap 将结构体切片转出[]map[string]interface{} func (s *toolSliceUtil) ConvertSliceToMap(slice interface{}) []map[string]interface{} { // 获取slice的值 sliceValue := reflect.ValueOf(slice) // 检查slice是否为切片类型 if sliceValue.Kind() != reflect.Slice { return []map[string]interface{}{} } // 创建一个空的map切片,用于存储转换后的结果 var result []map[string]interface{} // 遍历整个slice for i := 0; i < sliceValue.Len(); i++ { // 获取当前元素 item := sliceValue.Index(i) // 获取当前元素的值 itemValue := reflect.ValueOf(item.Interface()) // 检查当前元素是否为结构体类型 if itemValue.Kind() != reflect.Struct { return []map[string]interface{}{} } // 创建一个空的map,用于存储当前元素的字段名和对应的值 itemMap := make(map[string]interface{}) // 遍历当前元素的所有字段 for j := 0; j < itemValue.NumField(); j++ { // 获取当前字段的名称 fieldName := itemValue.Type().Field(j).Name // 获取当前字段的值 fieldValue := itemValue.Field(j).Interface() // 将字段名和对应的值添加到map中 itemMap[fieldName] = fieldValue } // 将当前元素转换为map后,将其添加到结果切片中 result = append(result, itemMap) } return result } // FindDiffVales 找到两个切片中不同的元素,返回两个切片中不同元素组成的切片 func (s *toolSliceUtil) FindDiffVales(slice1 []interface{}, slice2 []interface{}) []interface{} { // 创建一个空的切片,用于存储不同的元素 diffVales := make([]interface{}, 0) // 遍历第一个切片 for _, val1 := range slice1 { found := false // 在第二个切片中查找相同值 for _, val2 := range slice2 { if val1 == val2 { found = true break } } // 如果未找到相同值,则将其添加到不同值切片中 if !found { diffVales = append(diffVales, val1) } } // 遍历第二个切片 for _, val2 := range slice2 { found := false // 在第一个切片中查找相同值 for _, val1 := range slice1 { if val2 == val1 { found = true break } } // 如果未找到相同值,则将其添加到不同值切片中 if !found { diffVales = append(diffVales, val2) } } // 返回两个切片中不同元素组成的切片 return diffVales } // FindSameVales 找到两个切片中同同的元素,返回两个切片中相同同元素组成的切片 func (s *toolSliceUtil) FindSameVales(slice1 []interface{}, slice2 []interface{}) []interface{} { sameVales := make([]interface{}, 0) // 遍历第一个切片 for _, val1 := range slice1 { // 在第二个切片中查找相同值 for _, val2 := range slice2 { if val1 == val2 { sameVales = append(sameVales, val1) break } } } return sameVales } // FindOutVales 从slice1里剔除slice2存在的值 func (s *toolSliceUtil) FindOutVales(slice1 []interface{}, slice2 []interface{}) []interface{} { // 创建一个map,用于存储slice2中出现的所有元素 m := make(map[interface{}]bool) for _, i := range slice2 { m[i] = true } // 创建一个空的切片,用于存储slice1中不同于slice2的元素 var result []interface{} for _, i := range slice1 { if !m[i] { result = append(result, i) } } // 返回slice2独有的元素组成的切片 return result } /* 参数 slice 是一个 []map[string]interface{} 类型的切片,每个 map 中包含一条数据记录。 参数 key 和 name 都是字符串类型,分别表示按照哪个键进行分组和新生成的记录的名称。 返回值是一个 []map[string]interface{} 类型的切片,其中每个 map 表示一组已经分好组的数据记录。 */ // GroupByKey 将[]map[string]interface{}按某个字段分组 func (s *toolSliceUtil) GroupByKey(slice []map[string]interface{}, key string, name string) []map[string]interface{} { // 创建一个 map[interface{}][]interface{} 类型的变量 transformedData,用于存储已经分组后的数据。 transformedData := make(map[interface{}][]interface{}) // 遍历输入的每个 map[string]interface{} 类型的数据记录 d,在 transformedData 中找到对应的键 k,将其添加到分组后的列表中。 for _, d := range slice { k := d[key] if data, ok := transformedData[k]; ok { transformedData[k] = append(data, d) } else { transformedData[k] = []interface{}{d} } } // 创建一个 []map[string]interface{} 类型的切片 result,遍历 transformedData map 中的所有键值对, // 并将其转换为新的 map[string]interface{} 类型的数据记录,并添加到 result 切片中。 result := make([]map[string]interface{}, 0, len(transformedData)) for k, v := range transformedData { m := map[string]interface{}{ key: k, name: v, } result = append(result, m) } // 返回 result 切片即可。 return result } /* 如果某个元素的 key 对应的不是 int 类型,则返回一个空的 []int 类型的切片。 */ //MapListKeyToIntSlice 函数从输入的 []map[string]interface{} 类型的切片中提取指定 key 对应的 int 类型数值,并返回一个 []int 类型的切片。 func (s *toolSliceUtil) MapListKeyToIntSlice(list []map[string]interface{}, key string) []int { // 创建一个 []int 类型的切片 result,用于存储提取出来的 int 数值。 result := make([]int, len(list)) // 遍历输入的每个 map[string]interface{} 类型的数据记录 m,在其中找到 key 对应的值 v, // 如果 v 是 int 类型,则将其赋值给 result 切片对应的位置;否则,返回一个空的 []int 类型的切片。 for i, m := range list { if v, ok := m[key]; ok { if num, ok := v.(int); ok { result[i] = num } else { return []int{} } } else { return []int{} } } // 返回 result 切片即可。 return result } /* 参数 iList 是一个可变参数,可以接收任意数量的 []interface{} 类型的切片 返回值是合并并去重后的 []interface{} 类型的切片 */ //UniqueInterface 函数用于合并多个任意类型的切片并去重 func (s *toolSliceUtil) UniqueInterface(iList ...[]interface{}) []interface{} { // 创建一个 map[interface{}]bool 类型的变量 m,用于记录已经出现过的元素。 m := make(map[interface{}]bool) // 遍历输入的每个 []interface{} 类型的切片 ints,对于每个元素 i,将其添加到 m map 中。 for _, ints := range iList { for _, i := range ints { m[i] = true } } // 创建一个 []interface{} 类型的切片 result,遍历上一步中去重后的 m map 中的所有键,并将其添加到 result 切片中。 var result []interface{} for k := range m { result = append(result, k) } // 返回 result 切片即可。 return result } // SetNilToDefaultValueByMap 字典中所有键名在 keys 数组中出现过且对应的键值为 nil 的元素改为默认值 defaultValue func (s *toolSliceUtil) SetNilToDefaultValueByMap(m map[string]interface{}, keys []string, defaultValue interface{}) { for _, key := range keys { if val, ok := m[key]; ok && val == nil { m[key] = defaultValue } } } // SetNilToDefaultValueByMapV2 处理nil值,出现在keys的nil设置成[], 其余的nil设置成"" func (s *toolSliceUtil) SetNilToDefaultValueByMapV2(m map[string]interface{}, keys []string) { for key, val := range m { if val == nil { if s.Contains(keys, key) { m[key] = "[]" } else { m[key] = "" } } } } // SetNilToDefaultValueBySlice 切片中所有键名在 keys 数组中出现过且对应的键值为 nil 的元素改为默认值 defaultValue func (s *toolSliceUtil) SetNilToDefaultValueBySlice(slice []map[string]interface{}, keys []string, defaultValue interface{}) { for _, m := range slice { for _, key := range keys { if val, ok := m[key]; ok && val == nil { m[key] = defaultValue } } } } // SetNilToDefaultValueBySliceV2 处理nil值,出现在keys的nil设置成[], 其余的nil设置成"" func (s *toolSliceUtil) SetNilToDefaultValueBySliceV2(slice []map[string]interface{}, keys []string) { for _, m := range slice { for key, val := range m { if val == nil { if s.Contains(keys, key) { m[key] = []interface{}{} } else { m[key] = "" } } } } } /* isAsc 参数控制是否为升序排列。如果 isAsc 为 true,则按照升序排列;否则,按照降序排列。 sort.SliceStable 可能会导致浮点数字段排序出现问题 */ // SortByKey 函数按照指定的 key 对应的值,对输入的 []map[string]interface{} 类型的切片进行排序。 func (s *toolSliceUtil) SortByKey(slice []map[string]interface{}, key string, isAsc bool) { // 调用 sort.SliceStable 函数对 slice 进行排序,并提供一个函数作为比较器。 sort.SliceStable(slice, func(i, j int) bool { var less bool switch v := slice[i][key].(type) { case int: less = v < slice[j][key].(int) case int32: less = v < slice[j][key].(int32) case int64: less = v < slice[j][key].(int64) case float32: less = v < slice[j][key].(float32) case float64: less = v < slice[j][key].(float64) default: fmt.Println("unsupported type: $s", reflect.TypeOf(v)) return false } if isAsc { return less } return !less }) } /* str: 待解析的字符串 elementType: 切片元素的反射类型 返回值: 解析后的切片 */ //StringToSlice 将字符串解析为切片类型 func (s *toolSliceUtil) StringToSlice(str string, elementType reflect.Type) interface{} { sliceType := reflect.SliceOf(elementType) sliceValue := reflect.New(sliceType).Elem() err := json.Unmarshal([]byte(str), sliceValue.Addr().Interface()) if err != nil { fmt.Println(err) } return sliceValue.Interface() } // StringToSliceInt 将字符串解析为Int切片类型 func (s *toolSliceUtil) StringToSliceInt(str string) []int { var slice []int err := json.Unmarshal([]byte(str), &slice) if err != nil { fmt.Println(err) } return slice } // StringToMap 将字符串解析为字典类型 func (s *toolSliceUtil) StringToMap(str string) map[string]interface{} { if str == "" { return map[string]interface{}{} } var m map[string]interface{} err := json.Unmarshal([]byte(str), &m) if err != nil { fmt.Println(err) return map[string]interface{}{} } return m } // StringToMapSlice 将字符串解析为切片类型 func (s *toolSliceUtil) StringToMapSlice(str string) []map[string]interface{} { if str == "" { return []map[string]interface{}{} } var m []map[string]interface{} err := json.Unmarshal([]byte(str), &m) if err != nil { fmt.Println(err) return []map[string]interface{}{} } return m } ~~~