四,切片数组类型

77 阅读2分钟

一些切片类型的操作

  1. 声明数组
  2. 声明切片的方式
  3. 给切片 append 元素
  4. 切片扩容的逻辑
  5. 遍历切片
  6. 协程不安全
  7. 解决并发安全问题|加锁
  8. 在指定位置插入元素
  9. 判断一个元素是否在切片内
  10. 切片去重,也可以转化成map,然后再转化回来切片就可以去重了
// 1. 声明数组
// 方式一
arr := [5]int{1, 2, 3, 4, 5}
fmt.Println(arr) // [1 2 3 4 5]

// 方式二
var arr2 [4]int
arr2[0] = 3
fmt.Println(arr2)

// 2. 声明切片的方式
// 方式一
var s1 []int
if s1 == nil {
  fmt.Println("是空") // 是空
} else {
  fmt.Println("不是空")
}

// 方式二
s2 := []int{}
fmt.Println(s2)         // []

// 方式三
var s3 []int = make([]int, 0)
fmt.Println(s1, s2, s3) // [] [] []

// 方式四
var s4 []int = make([]int, 0, 4)
fmt.Println(s4)         // []

// 方式五
s5 := []int{1, 2, 3}
fmt.Println(s5)         // [1 2 3]

// 方式六
arr := [5]int{1, 2, 3, 4, 5}
var s6 []int
s6 = arr[1:4]
fmt.Println(s6)         // [2 3 4]

// 3. 给切片 append 元素
arr := []int{1, 2, 3}
arr = append(arr, 4)
fmt.Println(arr) // [1 2 3 4]

// 4. 切片扩容的逻辑
// https://blog.csdn.net/weixin_43204583/article/details/127986860
// 在双倍扩容之后,还在原数组的cap范围内,就双倍扩容
// 在 1.18 版本前,切片扩容,在容量小于1024时,以2倍大小扩容。超过1024后,以1.25倍扩容。
// 在扩容后切片的基础上,会根据长度和容量进行 roundupsize 。
// 在1.18版本后,切片扩容,在容量小于256时,以2倍大小扩容。超过256后,以(1.25倍+192)扩容。


// 5. 遍历切片
arr := []string{"a", "b", "c"}
for _, v := range arr {
  fmt.Println(v)      // a,b,c
}
for i := 0; i < len(arr); i++ {
  fmt.Println(arr[i]) // a,b,c
}

// 6. 协程不安全
arr := []int{}
	var wg sync.WaitGroup
	wg.Add(1000)
	for i := 0; i < 1000; i++ {
		go func() {
			arr = append(arr, 1)
			wg.Done()
		}()
	}
	wg.Wait()
	fmt.Println(len(arr)) // 957

fmt.Println(len(arr)) // 957 | 不符合期待

// 7. 解决并发安全问题|加锁
arr := []int{}
	var mx sync.Mutex     // sync.Mutex
	var wg sync.WaitGroup
	wg.Add(1000)
	for i := 0; i < 1000; i++ {
		go func() {
			mx.Lock()         // 加锁
			defer mx.Unlock() // 解锁
			arr = append(arr, 1)
			wg.Done()
		}()
	}
	wg.Wait()
	fmt.Println(len(arr)) // 1000

// 8. 在指定位置插入元素
// https://blog.csdn.net/weixin_42161901/article/details/127935472

// 9. 判断一个元素是否在切片内
// 方案一:遍历查询,复杂度O(n)
// InSlice 判断字符串是否在 slice 中。
func InSlice(items []string, item string) bool {
	for _, eachItem := range items {
		if eachItem == item {
			return true
		}
	}
	return false
}
// 方案二:转成map进行查询
// ConvertStrSlice2Map 将字符串 slice 转为 map[string]struct{}。
func ConvertStrSlice2Map(sl []string) map[string]struct{} {
	set := make(map[string]struct{}, len(sl))
	for _, v := range sl {
		set[v] = struct{}{} // struct{}{}不占用内存空间 
	}
	return set
}

// InMap 判断字符串是否在 map 中。
func InMap(m map[string]struct{}, s string) bool {
	_, ok := m[s]
	return ok
}

// 10.切片去重,也可以转化成map,然后再转化回来切片就可以去重了