Golang: 切片的奇技淫巧

629 阅读2分钟

1. 切片介绍

slice 名为切片,是 Go 中的可变长数组,是对底层数组的封装和引用。切片指向一个底层数组,并且包含长度和容量信息。未初始化切片的值为 nil。作用于切片的内建函数主要有四个,分别是 make、len、cap 和 append。make 用于创建切片,len 用于获取切片的长度,cap 用于获取切片的容量,append 用于向切片追加元素。

2. 声明切片

fib := make([]int, 0, 10)
var sli []int

3. 给切片添加元素

fib = append(sli, []int{1, 1, 2, 3}...)
func main() {
   
   fib := make([]interface{}, 0, 10)
   fib = insert(fib, 0, "a")
   fib = insert(fib, 0, 1)
   tmp := make(map[string]interface{})
   tmp["name"] = "ll"
   tmp["age"] = 18
   fib = insert(fib, 0, tmp)
   fmt.Println(fib)
}

func insert(slice []interface{}, index int, value interface{}) []interface{} {
   if index > len(slice) {
      return slice
   }
   if index == len(slice) {
      return append(slice, value)
   }
   sl := append(slice[:index+1], slice[index:]...)
   sl[index] = value
   return sl
}

4. 切片添加复杂元素

var x []map[string]interface{}
for i := 0; i < 100; i++ {
   c := make(map[string]interface{})
   c["name"] = "ll" + "_" + strconv.Itoa(i)
   c["age"] = i
   x = append(x, c)
}
fmt.Println(x)

5. 切片的增删改查

// 切片使用映射添加元素
func InsertSliceE(slice interface{}, index int, value interface{}) (interface{}, error) {
   fmt.Println(value)
   v := reflect.ValueOf(slice)
   if v.Kind() != reflect.Slice {
      return nil, errors.New("不是slice切片类型")
   }
   if index < 0 || index > v.Len() || reflect.TypeOf(slice).Elem() != reflect.TypeOf(value) {
      return nil, errors.New("value参数错误")
   }
   // 使用反射 新建一个切片
   dst := reflect.MakeSlice(reflect.TypeOf(slice), 0, 0)
   if index == v.Len() {
      // 将原切片写入新切片中
      dst = reflect.AppendSlice(dst, v.Slice(0, v.Len()))
      // 将元素加入切片中
      dst = reflect.Append(dst, reflect.ValueOf(value))
      return dst.Interface(), nil
   }
   dst = reflect.AppendSlice(dst, v.Slice(0, index+1))
   dst = reflect.AppendSlice(dst, v.Slice(index, v.Len()))
   // 对应下表 给切片更新元素
   dst.Index(index).Set(reflect.ValueOf(value))
   return dst.Interface(), nil
}

func DeleteSliceE(slice interface{}, index int) (interface{}, error) {
   v := reflect.ValueOf(slice)
   if v.Kind() != reflect.Slice {
      return nil, errors.New("不是slice切片类型")
   }
   if index < 0 || index > v.Len()-1 || v.Len() == 0 {
      return nil, errors.New("下标错误")
   }
   dst := reflect.MakeSlice(reflect.TypeOf(slice), 0, 0)
   dst = reflect.AppendSlice(dst, v.Slice(0, index))
   dst = reflect.AppendSlice(dst, v.Slice(index+1, v.Len()))
   return dst.Interface(), nil
}

func UpdateSliceE(slice interface{}, index int, value interface{}) (interface{}, error) {
   v := reflect.ValueOf(slice)
   if v.Kind() != reflect.Slice {
      return nil, errors.New("不是slice切片类型")
   }
   if index < 0 || index > v.Len() || reflect.TypeOf(slice).Elem() != reflect.TypeOf(value) {
      return nil, errors.New("传入参数不正确")
   }
   dst := reflect.MakeSlice(reflect.TypeOf(slice), 0, 0)
   dst = reflect.AppendSlice(dst, v.Slice(0, v.Len()))
   dst.Index(index).Set(reflect.ValueOf(value))
   return dst.Interface(), nil
}

func GetSliceIndexE(slice interface{}, value interface{}) ([]int, error) {
   v := reflect.ValueOf(slice)
   if v.Kind() != reflect.Slice {
      return nil, errors.New("不是slice切片类型")
   }
   if reflect.TypeOf(slice).Elem() != reflect.TypeOf(value) {
      return nil, errors.New("传入参数不正确")
   }
   var indexes []int
   for i := 0; i < v.Len(); i++ {
      if v.Index(i).Interface() == value {
         indexes = append(indexes, i)
      }
   }
   return indexes, nil
}