1 切片初始化 Out: 2 切片長度與容量 切片的長度就是它所包含的元素個數。 切片的容量是從它的第一個元素開始數,到其底層數組元素末尾的個數 Out: 3 賦值與傳參 Out 2~4 一個數組變數表示整個數組,它不是指向第一個元素的指針(不像 C 語言的數組)因此數組名通過%p 無法列印地址。 ...
1 切片初始化
1 func printSlice(s []int) { 2 fmt.Printf("len=%d cap=%d underlying array:%p, %v\n", len(s), cap(s), s, s) 3 } 4 5 func sliceInit() { 6 7 var s1 []int //聲明s1,並沒有初始化,此時s1是nil切片,沒有分配底層數組 8 if s1 == nil { 9 fmt.Println("s1 is nil") 10 } 11 12 s2 := []int{} 13 if s2 == nil { 14 fmt.Println("s2 is nil") 15 } 16 17 s3 := make([]int, 0) 18 if s3 == nil { 19 fmt.Println("s3 is nil!") 20 } 21 22 printSlice(s1) 23 printSlice(s2) 24 printSlice(s3) 25 } 26 func main(){ 27 sliceInit() 28 }
Out:
s1 is nil len=0 cap=0 underlying array:0x0, [] len=0 cap=0 underlying array:0x55c988, [] len=0 cap=0 underlying array:0x55c988, []
2 切片長度與容量
切片的長度就是它所包含的元素個數。
切片的容量是從它的第一個元素開始數,到其底層數組元素末尾的個數
func main() { s := []int{2, 3, 5, 7, 11, 13} printSlice(s) // Slice the slice to give it zero length. s = s[:0] printSlice(s) // Extend its length. s = s[:4] printSlice(s) // Drop its first two values. s = s[2:] printSlice(s) }
Out:
len=6 cap=6 underlying array:0xc04200a2a0, [2 3 5 7 11 13] len=0 cap=6 underlying array:0xc04200a2a0, [] len=4 cap=6 underlying array:0xc04200a2a0, [2 3 5 7] len=2 cap=4 underlying array:0xc04200a2b0, [5 7]
3 賦值與傳參
1 func sliceT() { 2 arrayA := [5]int{100, 200, 300, 400, 500} 3 fmt.Printf("arrayA: %p, %v\n", arrayA, arrayA) 4 fmt.Printf("arrayA: %p, %v\n", &arrayA, arrayA) 5 6 fmt.Printf("arrayA: %p, %v\n", &arrayA[0], arrayA) 7 fmt.Printf("arrayA: %p, %v\n", &arrayA[1], arrayA) 8 fmt.Printf("arrayA: %p, %v\n", &arrayA[2], arrayA) 9 fmt.Printf("arrayA: %p, %v\n", &arrayA[3], arrayA) 10 fmt.Printf("arrayA: %p, %v\n", &arrayA[4], arrayA) 11 12 slice := arrayA[1:3:4] 13 fmt.Printf("slice: %p, %v\n", slice, slice) 14 fmt.Printf("slice: %p, %v\n", &slice[0], slice) 15 fmt.Printf("slice: %p, %v\n", &slice[1], slice) 16 17 slice[0] = 0 18 fmt.Printf("slice: %p, %v\n", slice, slice) 19 fmt.Printf("arrayA: %p, %v\n", &arrayA, arrayA) 20 21 }
Out
3 arrayA: %!p([5]int=[100 200 300 400 500]), [100 200 300 400 500] 4 arrayA: 0xc04206c030, [100 200 300 400 500]
6 arrayA: 0xc04206c030, [100 200 300 400 500] 7 arrayA: 0xc04206c038, [100 200 300 400 500] 8 arrayA: 0xc04206c040, [100 200 300 400 500] 9 arrayA: 0xc04206c048, [100 200 300 400 500] 10 arrayA: 0xc04206c050, [100 200 300 400 500]
13 slice: 0xc04206c038, [200 300] 14 slice: 0xc04206c038, [200 300] 15 slice: 0xc04206c040, [200 300]
18 slice: 0xc04206c038, [0 300] 19 arrayA: 0xc04206c030, [100 0 300 400 500]
2~4
一個數組變數表示整個數組,它不是指向第一個元素的指針(不像 C 語言的數組)因此數組名通過%p 無法列印地址。 當一個數組變數被賦值或者被傳遞的時候,實際上會複製整個數組。 (為了避免複製數組,可以傳遞一個指向數組的指針)
6~9
int 在64機器上占8個位元組
12~15
切片語法 a[ low:high:cap ]; cap 表示切片容量
切片名通過%p 列印,輸出的是切片所引用的底層數組的地址
18~19
改變切片元素值就是改變其引用的數組的對應元素值
1 func sliceT() { 2 s := []int{1,2,3,4,5} 3 fmt.Printf("underlying array: %p, slice addr: %p\n", s, &s) 4 changeSlice(s) 5 fmt.Println(s) 6 } 7 8 func changeSlice(s []int) { 9 fmt.Printf("underlying array: %p, param slice addr: %p\n", s, &s) 10 s[1] = -1 11 }
Out:
underlying array: 0xc04206c030, slice addr: 0xc04204a3a0 underlying array: 0xc04206c030, param slice addr: 0xc04204a400 [1 -1 3 4 5]
1 func sliceT1() { 2 s := []int{1,2,3,4,5} 3 fmt.Printf("underlying array: %p, slice addr: %p\n", s, &s) 4 changeSlice1(s) 5 fmt.Println(s) 6 } 7 8 func changeSlice1(s []int) { 9 fmt.Printf("underlying array: %p, param slice addr: %p\n", s, &s) 10 s = append(s, 1) 11 }
Out:
underlying array: 0xc04200a2a0, slice addr: 0xc0420023e0 underlying array: 0xc04200a2a0, param slice addr: 0xc042002440 [1 2 3 4 5]
切片作為函數參數傳遞時是值傳遞,會拷貝一個切片,但形參和實參,擁有相同的底層數組引用。
更多內容: https://blog.go-zh.org/go-slices-usage-and-internals
https://www.jianshu.com/p/030aba2bff41