package main
import (
"fmt"
)
func main() {
fmt.Println("hello world!")
x := []int{1,3,4,6,7}
y := x[2:3]
fmt.Println(y)
fmt.Println(len(y))
fmt.Println(cap(y))
// 这里不会panic 因为cap(y) = 3. 其输出为 [4 6 7]
fmt.Println(y[0:3])
fmt.Println(y[:])
}
上面这段代码神奇的地方就是 注释的部分。 其原因可以参考这篇文章
https://tiancaiamao.gitbooks.io/go-internals/content/zh/02.2.html
关于append时, cap增长的算法 。
参考: https://studygolang.com/articles/18194?fr=sidebar
package main
import (
"fmt"
)
func main(){
a := []int{1,2,3}
b := append(a,4)
// 1. cap(a) = 3 double = 6 cap(b) = 4 < double ==> cap(b) = double = 6
fmt.Printf("cap(a)=%v,cap(b)=%v\n",cap(a),cap(b))
// 2. cap(a) = 3 double = 6 cap(b) = 7 > double ==> cap(b) = 7 ==> roundup +1 => cap(b) = 8
b2 := append(a, 4, 5, 6, 7)
fmt.Printf("cap(a)=%v,cap(b2)=%v\n", cap(a), cap(b2))
// 测试1024
c := make([]int, 1024, 1024)
fmt.Printf("cap(c)=%v,len(c)=%v\n", cap(c), len(c))
d := append(c, 1)
// 3. len(c) = 1024 , double = 1024 + 1024 / 4 = 1280 cap(d) = 1025 < double => cap(d) = double = 1280
fmt.Printf("cap(c)=%v,cap(d)=%v\n", cap(c), cap(d))
c1 := make([]int, 10, 1024)
fmt.Printf("cap(c1)=%v,len(c1)=%v\n", cap(c1), len(c1))
d1 := append(c1, 1)
// 4. 没有触发cap增长。
fmt.Printf("cap(c1)=%v,cap(d1)=%v\n", cap(c1), cap(d1))
// fmt.Println(d1) // [0 1 0 0 0 0 0 0 0 0 1]
// 5. 制造cap小于doublecap。
c2 := make([]int, 1023, 1024)
fmt.Printf("cap(c2)=%v,len(c2)=%v\n", cap(c2), len(c2))
d2 := append(c2, 1, 2, 4)
// 5. 这里虽然cap(c2) = 1024 但是len(c2) < 1024 => double = 2 * 1024 cap(d2) = 1025 < 2048 => cap(d2) = 2048
fmt.Printf("cap(c2)=%v,cap(d2)=%v\n", cap(c2), cap(d2))
// 5. cap小于doublecap。
c3 := make([]int, 1023, 1026)
fmt.Printf("cap(c2)=%v,len(c2)=%v\n", cap(c3), len(c3))
d3 := append(c3, 1, 2, 4, 5)
// cap(c3) = 1025 len(c3) = 1023 < 1024 => double = 2 * 1025 cap(d2) = 1025 < 2050 => 归一化到2^x = 2304 ... 神奇
// roundupsize 这个方法对于1024 < size < 32768 的数据进行了分段的映射。 应该是为了避免 内存的碎片化 ...
fmt.Printf("cap(c2)=%v,cap(d2)=%v\n", cap(c3), cap(d3))
}
还是很复杂的呢。
有疑问加站长微信联系(非本文作者)