SoFunction
Updated on 2025-03-01

Deep understanding of arrays and slices in Go

1. Type

An array is a value type. When assigning an array to another array, a copy is passed.

A slice is a reference type, and the array wrapped by the slice is called the underlying array of that slice.

Let's look at a piece of code

//a is an array. Note that the array is a fixed length. You must specify the length when initializing. If you do not specify the length, it will be sliced.a := [3]int{1, 2, 3}
//b is an array, a copy of ab := a
//c is a slice, a reference type, and the underlying array is ac := a[:]
for i := 0; i < len(a); i++ {
 a[i] = a[i] + 1
}
//After changing the value of a, b is a copy of a, b remains unchanged, c is a reference, and the value of c is changed(a) //[2,3,4]
(b) //[1 2 3]
(c) //[2,3,4]

2. Make

make can only be usedslice, map andchannel, so the following code generates aslice, is a reference type

s1 := make([]int, 0, 3)

for i := 0; i < cap(s1); i++ {
 s1 = append(s1, i)
}
s2 := s1
for i := 0; i < len(a); i++ {
 s1[i] = s1[i] + 1
}

(s1) //[1 2 3]
(s2) //[1 2 3]

3. When the limit of the underlying array is exceeded by the slice append

//n1 is the underlying array of n2n1 := [3]int{1, 2, 3}
n2 := n1[0:3]
("address of items in n1: ")
for i := 0; i &lt; len(n1); i++ {
 ("%p\n", &amp;n1[i])
}
//address of items in n1:
//0xc20801e160
//0xc20801e168
//0xc20801e170
("address of items in n2: ")
for i := 0; i &lt; len(n2); i++ {
 ("%p\n", &amp;n2[i])
}
//address of items in n2:
//0xc20801e160
//0xc20801e168
//0xc20801e170

//After performing append operation on n2, n2 exceeds j of the underlying array n1n2 = append(n2, 1)
("address of items in n1: ")
for i := 0; i &lt; len(n1); i++ {
 ("%p\n", &amp;n1[i])
}
//address of items in n1:
//0xc20801e160
//0xc20801e168
//0xc20801e170

("address of items in n2: ")
for i := 0; i &lt; len(n2); i++ {
 ("%p\n", &amp;n2[i])
}
//address of items in n2:
//0xc20803a2d0
//0xc20803a2d8
//0xc20803a2e0
//0xc20803a2e8

4. Quote "invalid"

Deletion is implementedsliceThe last oneitemFunctions of

func rmLast(a []int) {
 ("[rmlast] the address of a is %p", a)
 a = a[:len(a)-1]
 ("[rmlast] after remove, the address of a is %p", a)
}

After calling this function, the originalsliceNo change

func main() {
 xyz := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
 ("[main] the address of xyz is %p\n", xyz)
 rmLast(xyz)
 ("[main] after remove, the address of xyz is %p\n", xyz)
 ("%v", xyz) //[1 2 3 4 5 6 7 8 9]
}

The printed result is as follows:

[main] the address of xyz is 0xc2080365f0
[rmlast] the address of a is 0xc2080365f0
[rmlast] after remove, the address of a is 0xc2080365f0
[main] after remove, the address of xyz is 0xc2080365f0
[1 2 3 4 5 6 7 8 9]

Printed directly hereslicepointer value, becausesliceIt is a reference type, so the pointer values ​​are the same, so we change to printsliceCheck out the address

func rmLast(a []int) {
 ("[rmlast] the address of a is %p", &a)
 a = a[:len(a)-1]
 ("[rmlast] after remove, the address of a is %p", &a)
}
func main() {
 xyz := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
 ("[main] the address of xyz is %p\n", &xyz)
 rmLast(xyz)
 ("[main] after remove, the address of xyz is %p\n", &xyz)
 ("%v", xyz) //[1 2 3 4 5 6 7 8 9]
}

result:

[main] the address of xyz is 0xc20801e1e0
[rmlast] the address of a is 0xc20801e200
[rmlast] after remove, the address of a is 0xc20801e200
[main] after remove, the address of xyz is 0xc20801e1e0
[1 2 3 4 5 6 7 8 9]

This time you can seesliceWhen passing it into a function as a function parameter, it actually copied a copyslice,becausesliceIt's a pointer, so from the perspective of phenomenon,sliceIt's a reference type

Summarize

The above is the entire content of this article. I hope it will be of some help to everyone's study or work. If you have any questions, you can leave a message to communicate.