Notes on golang slice

Keywords: Go C

1 slice initialization

 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   //Declare s1, and it is not initialized. At this time, s1 is nil slice, and the underlying array is not allocated
 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 slice length and capacity

 

The length of a slice is the number of elements it contains.

The capacity of a slice is the number from its first element to the end of its underlying array element

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 assignment and parameter passing

 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

An array variable represents the entire array. It is not a pointer to the first element (unlike an array in C language). Therefore, the array name cannot print the address through% p. When an array variable is assigned or passed, the entire array is actually copied. (to avoid copying arrays, pass a pointer to the array)

6~9

int takes 8 bytes on 64 machines

12~15

Slice syntax a [low: high: cap]; cap means slice capacity

The slice name is printed by% p, and the output is the address of the underlying array referenced by the slice

18~19

Changing the slice element value is changing the corresponding element value of the array it references

 

 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]

When a slice is passed as a function parameter, it is a value passing. It copies a slice, but the formal parameter and the actual parameter have the same underlying array reference.

 

 

More: https://blog.go-zh.org/go-slices-usage-and-internals

                   https://www.jianshu.com/p/030aba2bff41

Posted by Imad on Tue, 07 Jan 2020 02:09:49 -0800