切片踩坑:https://blog.csdn.net/a775189488/article/details/114278113
切片技巧:https://www.liwenzhou.com/posts/Go/slice_tricks/
截取
s = s[low : high : max]
low为截取的起始下标(含),
high为窃取的结束下标(不含high),
max为切片保留的原切片的最大下标(不含max)
即新切片从老切片的low下标元素开始,len = high - low, cap = max - low;
high 和 max一旦超出在老切片中越界,就会发生runtime err,slice out of range。
另外如果省略第三个参数的时候,第三个参数默认和第二个参数相同,即len = cap (这条不准确)
s := []int{1, 1, 1, 1, 1}s1 := s[1:3]fmt.Println(s1)fmt.Println(len(s1)) // 2fmt.Println(cap(s1)) // 4s := []int{1, 1, 1, 1, 1}s1 := s[1:3:4]fmt.Println(s1)fmt.Println(len(s1)) // 2fmt.Println(cap(s1)) // 3
不会改变原数组 sfunc myAppend(s []int) []int {s = append(s, 100)return s}会改变原数组 sfunc myAppendPtr(s *[]int) {// 会改变外层 s 本身*s = append(*s, 100)return}
拷贝
b := make([]int, 4)copy(b, a)b := make([]int, 0 , 4)copy(b, a) //这种没效果// 拷贝方式比较慢,不过添加元素比较快b = append([]T(nil), a...)b = append(a[:0:0], a...)
剪切或删除操作可能引起的内存泄露
需要特别注意的是。如果切片a中的元素是一个指针类型或包含指针字段的结构体类型(需要被垃圾回收),
普通的剪切和删除的代码会存在一个潜在的内存泄漏问题:一些具有值的元素仍被切片a引用,因此无法被垃圾回收机制回收掉。
下面的代码可以解决这个问题
// 剪切copy(a[i:], a[j:])for k, n := len(a)-j+i, len(a); k < n; k++ {a[k] = nil // 或类型T的零值}a = a[:len(a)-j+i]// 删除copy(a[i:], a[i+1:])a[len(a)-1] = nil // 或类型T的零值a = a[:len(a)-1]
过滤
// 这代码是真的骚,牛啊n := 0for _, x := range a {if keep(x) {a[n] = x // 保留该元素n++}}a = a[:n] // 截取切片中需保留的元素
扩容策略
func growslice(et *_type, old slice, cap int) slice {newcap := old.capdoublecap := newcap + newcapif cap > doublecap {newcap = cap} else {if old.len < 1024 {newcap = doublecap} else {for 0 < newcap && newcap < cap {newcap += newcap / 4}if newcap <= 0 {newcap = cap}}}}

