I have used a lot of Slice. Recently, when I was preparing for the interview, I found that I did not know much about slice. If I asked some dramatic questions, I found that I could not give the correct answers at the first time.

package main

import (
	"fmt"
)

func main() {


	a := make([]int, 10)
	a = append(a, 1, 2)
	FuncA(a)
	fmt.Println(a)
	a[0] = 44
	FuncA(a)
	fmt.Println(a)
}

func FuncA(b []int) {
	b[0] =19
}
Copy the code

The sample output above is:

[19 0 0 0 0 0 0 0 0 1 2] [19 0 0 0 0 0 0 0 0 0 1 2]Copy the code

From the output, in general, there are two questions:

  • After I instantiate a slice, APPend two elements, why not the first and second elements of the slice
  • I pass a value, call FuncA, why I can change the contents of my slice inside its function

If you have a problem, you will understand the principle of slicing. Let’s look at the first question. After the slice is instantiated, the append operation is performed

Makeslice when we execute a make([]int, 10) statement, we call a makeslice function underneath.

    0x002f 00047 (main2.go:10)	LEAQ	type.int(SB), AX
	0x0036 00054 (main2.go:10)	PCDATA	$2, $0
	0x0036 00054 (main2.go:10)	MOVQ	AX, (SP)
	0x003a 00058 (main2.go:10)	MOVQ	$10, 8(SP)
	0x0043 00067 (main2.go:10)	MOVQ	$10, 16(SP)
	0x004c 00076 (main2.go:10)	CALL	runtime.makeslice(SB)
Copy the code

Int and the length of the underlying array. The following two parameters are the slice length and the underlying array length.

func makeslice(et *_type, len, cap int) unsafe.Pointer {
	mem, overflow := math.MulUintptr(et.size, uintptr(cap))
	if overflow || mem > maxAlloc || len < 0 || len > cap {
		// NOTE: Produce a 'len out of range' error instead of a
		// 'cap out of range' error when someone does make([]T, bignumber).
		// 'cap out of range' is true too, but since the cap is only being
		// supplied implicitly, saying len is clearer.
		// See golang.org/issue/4085.
		mem, overflow := math.MulUintptr(et.size, uintptr(len))
		if overflow || mem > maxAlloc || len < 0 {
			panicmakeslicelen()
		}
		panicmakeslicecap()
	}

	return mallocgc(mem, et, true)
}
Copy the code

Makeslice first checks for a stack overflow. If it overflows, it panic; otherwise, it calls mallocGC to allocate resources

func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer 
Copy the code

Assign an object of size. Small objects are allocated from the free list of per-P cache. Large objects (> 32 kB) are allocated directly from the heap. The mallocgc argument is the size of memory to allocate :mem= type.int.size * cap. The second parameter is the element type. The third argument is a bool, and if NeedZero is true, the returned range of memory is zero. The return value from this method is the address of the allocated resource. Once the above action is complete, it is time to assign the variable

	0x004c 00076 (main2.go:10)	CALL	runtime.makeslice(SB)
	0x0051 00081 (main2.go:10)	PCDATA	$2, $1
	0x0051 00081 (main2.go:10)	MOVQ	24(SP), AX
	0x0056 00086 (main2.go:10)	MOVQ	AX, "".a+112(SP)
	0x005b 00091 (main2.go:10)	MOVQ	$10, "".a+120(SP)
	0x0064 00100 (main2.go:10)	MOVQ	$10, "".a+128(SP)
Copy the code

The assignment is made up of three parts: the allocated memory address, the slice length, and the underlying array length.

Let’s see what Slice does when we call the append function to add elements

	0x0070 00112 (main2.go:11)	JMP	114
	0x0072 00114 (main2.go:11)	PCDATA	$2, $2
	0x0072 00114 (main2.go:11)	LEAQ	type.int(SB), CX
	0x0079 00121 (main2.go:11)	PCDATA	$2, $1
	0x0079 00121 (main2.go:11)	MOVQ	CX, (SP)
	0x007d 00125 (main2.go:11)	PCDATA	$2, $0
	0x007d 00125 (main2.go:11)	MOVQ	AX, 8(SP)
	0x0082 00130 (main2.go:11)	MOVQ	$10, 16(SP)
	0x008b 00139 (main2.go:11)	MOVQ	$10, 24(SP)
	0x0094 00148 (main2.go:11)	MOVQ	$12, 32(SP)
	0x009d 00157 (main2.go:11)	CALL	runtime.growslice(SB)
	0x00a2 00162 (main2.go:11)	PCDATA	$2, $1
	0x00a2 00162 (main2.go:11)	MOVQ	40(SP), AX
	0x00a7 00167 (main2.go:11)	MOVQ	48(SP), CX
	0x00ac 00172 (main2.go:11)	MOVQ	56(SP), DX
	0x00b1 00177 (main2.go:11)	ADDQ	$2, CX
	0x00b5 00181 (main2.go:11)	JMP	183
	0x00b7 00183 (main2.go:11)	MOVQ	$1, 80(AX)
	0x00bf 00191 (main2.go:11)	MOVQ	$2, 88(AX)
	0x00c7 00199 (main2.go:11)	PCDATA	$0, $1
	0x00c7 00199 (main2.go:11)	MOVQ	AX, "".a+112(SP)
	0x00cc 00204 (main2.go:11)	MOVQ	CX, "".a+120(SP)
	0x00d1 00209 (main2.go:11)	MOVQ	DX, "".a+128(SP)
Copy the code

We found that before adding elements, slice was expanded by calling the Runtime. growslice function, prototyped as

func growslice(et *_type, old slice, cap int) slice

The function takes three arguments: the first argument is the element type type.int, the second argument is the original slice before expansion, and the third argument is the size of the new slice, which in this case is 12. After the call is complete, the new slice is returned. After the new slice performs a length increment of 2, the new element is placed in the slice array at the address of the offset 80 and 88.

	0x00b7 00183 (main2.go:11)	MOVQ	$1, 80(AX)
	0x00bf 00191 (main2.go:11)	MOVQ	$2, 88(AX)
Copy the code

This is the first problem, which appends the data to the end of the array.

After all the action is done, the assignment is repeated

    0x00c7 00199 (main2.go:11)	MOVQ	AX, "".a+112(SP)
	0x00cc 00204 (main2.go:11)	MOVQ	CX, "".a+120(SP)
	0x00d1 00209 (main2.go:11)	MOVQ	DX, "".a+128(SP)
Copy the code

The FuncA function is then called

    0x00d9 00217 (main2.go:12)	MOVQ	AX, (SP)
	0x00dd 00221 (main2.go:12)	MOVQ	CX, 8(SP)
	0x00e2 00226 (main2.go:12)	MOVQ	DX, 16(SP)
	0x00e7 00231 (main2.go:12)	CALL	"".FuncA(SB)
Copy the code

The interesting thing about this call is that FuncA provides the underlying slice structure of a slice to FuncA, which supports the second question, why my changes to slice elements in FuncA can affect my original slice. Look again at FuncA’s function calls

"".FuncA STEXT nosplit size=50 args=0x18 locals=0x8 0x0000 00000 (main2.go:19) TEXT "".FuncA(SB), NOSPLIT|ABIInternal, $8-24 0x0000 00000 (main2.go:19) SUBQ $8, SP 0x0004 00004 (main2.go:19) MOVQ BP, (SP) 0x0008 00008 (main2.go:19) LEAQ (SP), BP 0x000c 00012 (main2.go:19) FUNCDATA $0, Gclocals · 1 a65e721a2ccc325b382662e7ffee780 (SB) 0 x000c 00012 (main2. Go: 19) FUNCDATA $1. Gclocals · 69 c1753bd5f81501d95132d08af04464 (SB) 0 x000c 00012 (main2. Go: 19) FUNCDATA $3, Gclocals · 9 fb7f0986f647f17cb53dda1484e0f7a (SB) 00012 (20) main2. Go: 0 x000c PCDATA $2, $1 0x000c 00012 (main2.go:20) PCDATA $0, $0 0x000c 00012 (main2.go:20) MOVQ "".b+16(SP), AX 0x0011 00017 (main2.go:20) PCDATA $0, $1 0x0011 00017 (main2.go:20) CMPQ "".b+24(SP), $0 0x0017 00023 (main2.go:20) JHI 27 0x0019 00025 (main2.go:20) JMP 43 0x001b 00027 (main2.go:20) PCDATA $2, $0 0x001b 00027 (main2.go:20) MOVQ $19, (AX) 0x0022 00034 (main2.go:21) MOVQ (SP), BP 0x0026 00038 (main2.go:21) ADDQ $8, SP 0x002a 00042 (main2.go:21) RET 0x002b 00043 (main2.go:20) CALL runtime.panicindex(SB) 0x0030 00048 (main2.go:20) UNDEF 0x0000 48 83 ec 08 48 89 2c 24 48 8d 2c 24 48 8b 44 24 H... H.,$H.,$H.D$ 0x0010 10 48 83 7c 24 18 00 77 02 eb 10 48 c7 00 13 00 .H.|$.. w... H.... 0x0020 00 00 48 8b 2c 24 48 83 c4 08 c3 e8 00 00 00 00 .. H.,$H......... 0x0030 0f 0b .. rel 44+4 t=8 runtime.panicindex+0Copy the code

An index comparison is performed first, and if it is 0, the assignment is performed. Then retrieve the resources and return.

Let’s take a look at some interesting examples:

package main

import (
	"fmt"
)

func main() {
	a := make([]int, 10)
	FuncA(a)
	fmt.Println(a)
}

func FuncA(b []int) {
	b = append(b, 1, 2)
}
Copy the code

Same example, except that in FuncA we perform the append operation instead of the index assignment. First take a look at the output of the program:

[0 0 0 0 0 0 0 0 0Copy the code

Notice that the original slice value has not been modified. What the hell is that? Can it be modified?

0x0021 00033 (main2.go:11) MOVQ "".b+96(SP), AX 0x0026 00038 (main2.go:11) LEAQ 2(AX), CX 0x002a 00042 (main2.go:11) PCDATA $2, $1 0x002a 00042 (main2.go:11) MOVQ "".b+88(SP), DX 0x002f 00047 (main2.go:11) PCDATA $0, $1 0x002f 00047 (main2.go:11) MOVQ "".b+104(SP), BX 0x0034 00052 (main2.go:11) CMPQ CX, BX 0x0037 00055 (main2.go:11) JLS 59 0x0039 00057 (main2.go:11) JMP 103 0x003b 00059 (main2.go:11) PCDATA $2, $-2 0x003b 00059 (main2.go:11) PCDATA $0, $-2 0x003b 00059 (main2.go:11) JMP 61 0x003d 00061 (main2.go:11) PCDATA $2, $1 0x003d 00061 (main2.go:11) PCDATA $0, $1 0x003d 00061 (main2.go:11) MOVQ $1, (DX)(AX*8) 0x0045 00069 (main2.go:11) MOVQ $2, 8(DX)(AX*8) 0x004e 00078 (main2.go:11) PCDATA $2, $0 0x004e 00078 (main2.go:11) MOVQ DX, "".b+88(SP) 0x0053 00083 (main2.go:11) MOVQ CX, "".b+96(SP) 0x0058 00088 (main2.go:11) MOVQ BX, "".b+104(SP) 0x005d 00093 (main2.go:12) MOVQ 72(SP), BP 0x0062 00098 (main2.go:12) ADDQ $80, SP 0x0066 00102 (main2.go:12) RET 0x0067 00103 (main2.go:11) PCDATA $2, $1 0x0067 00103 (main2.go:11) MOVQ AX, "".. autotmp_1+64(SP) 0x006c 00108 (main2.go:11) PCDATA $2, $2 0x006c 00108 (main2.go:11) LEAQ type.int(SB), SI 0x0073 00115 (main2.go:11) PCDATA $2, $1 0x0073 00115 (main2.go:11) MOVQ SI, (SP) 0x0077 00119 (main2.go:11) PCDATA $2, $0 0x0077 00119 (main2.go:11) MOVQ DX, 8(SP) 0x007c 00124 (main2.go:11) MOVQ AX, 16(SP) 0x0081 00129 (main2.go:11) MOVQ BX, 24(SP) 0x0086 00134 (main2.go:11) MOVQ CX, 32(SP) 0x008b 00139 (main2.go:11) CALL runtime.growslice(SB) 0x0090 00144 (main2.go:11) PCDATA $2, $1 0x0090 00144 (main2.go:11) MOVQ 40(SP), DX 0x0095 00149 (main2.go:11) MOVQ 48(SP), AX 0x009a 00154 (main2.go:11) MOVQ 56(SP), BX 0x009f 00159 (main2.go:11) LEAQ 2(AX), CX 0x00a3 00163 (main2.go:11) MOVQ "".. autotmp_1+64(SP), AX 0x00a8 00168 (main2.go:11) JMP 61Copy the code

First determine whether growslice is needed. If it is, growslice is performed first, and then the element is appraised. Appraising is also very simple, that is, the address of the register is calculated, and then the value is moved to the specified value.

0x003d 00061 (main2.go:11)	MOVQ	$1, (DX)(AX*8)
	0x0045 00069 (main2.go:11)	MOVQ	$2, 8(DX)(AX*8)
Copy the code

Perform the assignment after completion

	0x004e 00078 (main2.go:11)	MOVQ	DX, "".b+88(SP)
	0x0053 00083 (main2.go:11)	MOVQ	CX, "".b+96(SP)
	0x0058 00088 (main2.go:11)	MOVQ	BX, "".b+104(SP)
Copy the code

The operation of the above function is to assign a value after the offset of the DX register +AX register of the newly allocated underlying array in the case of expansion. In this case, b acts as an independent slice and the value is placed in the underlying array of the slice. When the FuncA function returns, it has no effect on the original slice. The following example illustrates the situation better

Package main import (" FMT ") func main() {a := make([]int, 10, 10) b := a b = append(b,1,2) b[0] =19 FMT.Println(a)}Copy the code

The result is [0 0 0 0 0 0 0 0 0 0 0 0 0 0. Append determines whether it needs to be expanded, that is, whether its cap(the underlying array length) is sufficient. If not enough, the expansion of the operation, then allocates a new basic array, then b and they don’t have a contact, does not share the same underlying array again, but if no expansion operation, the underlying array, so that they will share the same underlying array, but its what you see is different.

The above example is an extreme case. Let’s look at another case where growslice is not needed to see if it makes any difference.

package main



func main() {
	a := make([]int, 10, 20)
	FuncA(a)
}

func FuncA(b []int) {
	b = append(b, 1, 2)
}
Copy the code

Let’s take a look at its output:

[0 0 0 0 0 0 0 0 0Copy the code

It is strange that I allocated such a large cap slice, but in FuncA, growslice operation was not required, so it did not affect the original slice. It’s reasonable to suspect that all of this is due to the append function, but what does Append actually do?

The append function is built into Golang and is declared as:

func append(slice []Type, elems ... Type) []TypeCopy the code

That is, the built-in append function appends elements to the end of slice, and if it has enough capacity, the target can be resliced to accommodate the new elements. If there is not enough capacity, a new underlying array is allocated. Append returns the updated slice. Therefore, it is necessary to store the results of the append, usually in a variable that holds the slice itself, for example:

slice = append(slice, elem1, elem2)
slice = append(slice, anotherSlice...)
Copy the code

As a special case, it is also legal to append a string to a byte slice, like this:

slice = append([]byte("hello "), "world"...)
Copy the code

For a simpler operation, let’s see:

Package main import (" FMT ") func main() {a := make([]int, 10, 20) b := a b = append(b,1,2) FMT.Println(a)}Copy the code

The result is the same, the output is [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

However, index modification of a slice’s underlying array can be implemented through B, for example

Package main import (" FMT ") func main() {a := make([]int, 10, 20) b := a b = append(b,1,2) b[0] =19 FMT.Println(a)}Copy the code

The output is :[19 0 0 0 0 0 0 0 0 0 0 0 0. The underlying array is the same as the append array, and does not affect a slice. A and B only share the same part, and their additions are not shared.

There’s another interesting situation

package main

import (
	"fmt"
)

func main() {
	a := make([]int, 10, 10)
	FuncA(a)
	fmt.Println(a)
}

func FuncA(b []int) {
	for i, v :=range b {
		v += 1
	}
}
Copy the code

The output is: [0 0 0 0 0 0 0 0 0 0]

"".FuncA STEXT nosplit size=139 args=0x18 locals=0x40 0x0000 00000 (main2.go:9) TEXT "".FuncA(SB), NOSPLIT|ABIInternal, $64-24 0x0000 00000 (main2.go:9) SUBQ $64, SP 0x0004 00004 (main2.go:9) MOVQ BP, 56(SP) 0x0009 00009 (main2.go:9) LEAQ 56(SP), BP 0x000e 00014 (main2.go:9) FUNCDATA $0, Gclocals · 2 d7c1615616d4cf40d01b3385155ed6e (SB) 00014 (9) main2. Go: 0 x000e FUNCDATA $1, Gclocals · 6 d81f9fc90b2254ac2f1067a7bf2c67c (SB) 00014 (9) main2. Go: 0 x000e FUNCDATA $3, Gclocals · db688afbc90e26183a53c9ad23b80c29 (SB) 0 x000e 00014 (main2. Go: 10) PCDATA $2, $0 0x000e 00014 (main2.go:10) PCDATA $0, $0 0x000e 00014 (main2.go:10) MOVQ "".b+88(SP), AX 0x0013 00019 (main2.go:10) MOVQ "".b+80(SP), CX 0x0018 00024 (main2.go:10) PCDATA $2, $1 0x0018 00024 (main2.go:10) PCDATA $0, $1 0x0018 00024 (main2.go:10) MOVQ "".b+72(SP), DX 0x001d 00029 (main2.go:10) PCDATA $2, $0 0x001d 00029 (main2.go:10) PCDATA $0, $2 0x001d 00029 (main2.go:10) MOVQ DX, "".. autotmp_2+32(SP) 0x0022 00034 (main2.go:10) MOVQ CX, "".. autotmp_2+40(SP) 0x0027 00039 (main2.go:10) MOVQ AX, "".. autotmp_2+48(SP) 0x002c 00044 (main2.go:10) MOVQ $0, "".. autotmp_3+24(SP) 0x0035 00053 (main2.go:10) MOVQ "".. autotmp_2+40(SP), AX 0x003a 00058 (main2.go:10) MOVQ AX, "".. autotmp_4+16(SP) 0x003f 00063 (main2.go:10) JMP 65 0x0041 00065 (main2.go:10) MOVQ "".. autotmp_4+16(SP), AX 0x0046 00070 (main2.go:10) CMPQ "".. autotmp_3+24(SP), AX 0x004b 00075 (main2.go:10) JLT 79 0x004d 00077 (main2.go:10) JMP 129 0x004f 00079 (main2.go:10) MOVQ "".. autotmp_3+24(SP), AX 0x0054 00084 (main2.go:10) SHLQ $3, AX 0x0058 00088 (main2.go:10) PCDATA $2, $2 0x0058 00088 (main2.go:10) ADDQ "".. autotmp_2+32(SP), AX 0x005d 00093 (main2.go:10) PCDATA $2, $0 0x005d 00093 (main2.go:10) MOVQ (AX), AX 0x0060 00096 (main2.go:10) MOVQ AX, "".. autotmp_5+8(SP) 0x0065 00101 (main2.go:10) MOVQ AX, "".v(SP) 0x0069 00105 (main2.go:11) INCQ AX 0x006c 00108 (main2.go:11) MOVQ AX, "".v(SP) 0x0070 00112 (main2.go:11) JMP 114 0x0072 00114 (main2.go:10) MOVQ "".. autotmp_3+24(SP), AX 0x0077 00119 (main2.go:10) INCQ AX 0x007a 00122 (main2.go:10) MOVQ AX, "".. autotmp_3+24(SP) 0x007f 00127 (main2.go:10) JMP 65 0x0081 00129 (<unknown line number>) PCDATA $0, $1 0x0081 00129 (<unknown line number>) MOVQ 56(SP), BP 0x0086 00134 (<unknown line number>) ADDQ $64, SP 0x008a 00138 (<unknown line number>) RET 0x0000 48 83 ec 40 48 89 6c 24 38 48 8d 6c 24 38 48 8b H.. @H.l$8H.l$8H. 0x0010 44 24 58 48 8b 4c 24 50 48 8b 54 24 48 48 89 54 D$XH.L$PH.T$HH.T 0x0020 24 20 48 89 4c 24 28 48 89 44 24 30 48 c7 44 24 $ H.L$(H.D$0H.D$ 0x0030 18 00 00 00 00 48 8b 44 24 28 48 89 44 24 10 eb ..... H.D$(H.D$.. 0x0040 00 48 8b 44 24 10 48 39 44 24 18 7c 02 eb 32 48 .H.D$.H9D$.|.. 2H 0x0050 8b 44 24 18 48 c1 e0 03 48 03 44 24 20 48 8b 00 .D$.H... H.D$ H.. 0x0060 48 89 44 24 08 48 89 04 24 48 ff c0 48 89 04 24 H.D$.H.. $H.. H.. $ 0x0070 eb 00 48 8b 44 24 18 48 ff c0 48 89 44 24 18 eb .. H.D$.H.. H.D$.. 0x0080 c0 48 8b 6c 24 38 48 83 c4 40 c3 .H.l$8H.. @.Copy the code

The result is different if you change it to the following form:

package main

import (
	"fmt"
)

func main() {
	a := make([]int, 10, 10)
	FuncA(a)
	fmt.Println(a)
}

func FuncA(b []int) {
	for i, _ :=range b {
		b[i] += 1
	}
}
Copy the code

The result output is: [1 1 1 1 1 1 1 1 1 1

"".FuncA STEXT nosplit size=135 args=0x18 locals=0x20 0x0000 00000 (main2.go:9) TEXT "".FuncA(SB), NOSPLIT|ABIInternal, $32-24 0x0000 00000 (main2.go:9) SUBQ $32, SP 0x0004 00004 (main2.go:9) MOVQ BP, 24(SP) 0x0009 00009 (main2.go:9) LEAQ 24(SP), BP 0x000e 00014 (main2.go:9) FUNCDATA $0, Gclocals · 1 a65e721a2ccc325b382662e7ffee780 (SB) 00014 (9) main2. Go: 0 x000e FUNCDATA $1, Gclocals · 69 c1753bd5f81501d95132d08af04464 (SB) 00014 (9) main2. Go: 0 x000e FUNCDATA $3, Gclocals · 7 cae486b9f11463edb9d0e91d30ff0f7 (SB) 0 x000e 00014 (main2. Go: 10) PCDATA $2, $0 0x000e 00014 (main2.go:10) PCDATA $0, $0 0x000e 00014 (main2.go:10) MOVQ $0, "".. autotmp_2+16(SP) 0x0017 00023 (main2.go:10) MOVQ "".b+48(SP), AX 0x001c 00028 (main2.go:10) MOVQ AX, "".. autotmp_3+8(SP) 0x0021 00033 (main2.go:10) JMP 35 0x0023 00035 (main2.go:10) MOVQ "".. autotmp_3+8(SP), AX 0x0028 00040 (main2.go:10) CMPQ "".. autotmp_2+16(SP), AX 0x002d 00045 (main2.go:10) JLT 49 0x002f 00047 (main2.go:10) JMP 118 0x0031 00049 (main2.go:10) MOVQ "".. autotmp_2+16(SP), AX 0x0036 00054 (main2.go:10) MOVQ AX, "".i(SP) 0x003a 00058 (main2.go:11) PCDATA $2, $1 0x003a 00058 (main2.go:11) MOVQ "".b+40(SP), CX 0x003f 00063 (main2.go:11) CMPQ "".b+48(SP), AX 0x0044 00068 (main2.go:11) JHI 72 0x0046 00070 (main2.go:11) JMP 116 0x0048 00072 (main2.go:11) PCDATA $2, $0 0x0048 00072 (main2.go:11) MOVQ (CX)(AX*8), CX 0x004c 00076 (main2.go:11) PCDATA $2, $2 0x004c 00076 (main2.go:11) MOVQ "".b+40(SP), DX 0x0051 00081 (main2.go:11) INCQ CX 0x0054 00084 (main2.go:11) CMPQ "".b+48(SP), AX 0x0059 00089 (main2.go:11) JHI 93 0x005b 00091 (main2.go:11) JMP 114 0x005d 00093 (main2.go:11) PCDATA $2, $0 0x005d 00093 (main2.go:11) MOVQ CX, (DX)(AX*8) 0x0061 00097 (main2.go:11) JMP 99 0x0063 00099 (main2.go:10) MOVQ "".. autotmp_2+16(SP), AX 0x0068 00104 (main2.go:10) INCQ AX 0x006b 00107 (main2.go:10) MOVQ AX, "".. autotmp_2+16(SP) 0x0070 00112 (main2.go:10) JMP 35 0x0072 00114 (main2.go:11) PCDATA $2, $-2 0x0072 00114 (main2.go:11) PCDATA $0, $-2 0x0072 00114 (main2.go:11) JMP 128 0x0074 00116 (main2.go:11) JMP 128 0x0076 00118 (<unknown line number>) MOVQ 24(SP), BP 0x007b 00123 (<unknown line number>) ADDQ $32, SP 0x007f 00127 (<unknown line number>) RET 0x0080 00128 (main2.go:11) PCDATA $2, $0 0x0080 00128 (main2.go:11) PCDATA $0, $1 0x0080 00128 (main2.go:11) CALL runtime.panicindex(SB) 0x0085 00133 (main2.go:11) UNDEF 0x0000 48 83 ec 20 48 89 6c 24 18 48 8d 6c 24 18 48 c7 H.. H.l$.H.l$.H. 0x0010 44 24 10 00 00 00 00 48 8b 44 24 30 48 89 44 24 D$..... H.D$0H.D$ 0x0020 08 eb 00 48 8b 44 24 08 48 39 44 24 10 7c 02 eb ... H.D$.H9D$.|.. 0x0030 45 48 8b 44 24 10 48 89 04 24 48 8b 4c 24 28 48 EH.D$.H.. $H.L$(H 0x0040 39 44 24 30 77 02 eb 2c 48 8b 0c c1 48 8b 54 24 9D$0w.. ,H... H.T$ 0x0050 28 48 ff c1 48 39 44 24 30 77 02 eb 15 48 89 0c (H.. H9D$0w... H.. 0x0060 c2 eb 00 48 8b 44 24 10 48 ff c0 48 89 44 24 10 ... H.D$.H.. H.D$. 0x0070 eb b1 eb 0c eb 0a 48 8b 6c 24 18 48 83 c4 20 c3 ...... H.l$.H.. . 0x0080 e8 00 00 00 00 0f 0b ....... rel 129+4 t=8 runtime.panicindex+0Copy the code

Conclusion:

1. Append Operation Without expansion, the new slice and the old slice share the underlying array, and the modification of the new slice through the index affects the old slice

2. The so-called sharing of the underlying array, only share its common part, as for the unique part, the parties can not modify and view

3. When the for loop iterates through slice, the value is a copy of the value, and its modification does not affect the underlying slice data

Articles in this series:

  • I probably wouldn’t use Golang slice
  • I probably wouldn’t use Golang’s map
  • I probably wouldn’t use Golang’s channel
  • I probably wouldn’t use Golang’s Goroutines

If you have any questions, please leave a comment