内容简介:使用了很多的slice,最近再准备面试的时候,才发现,自己对他是一知半解的,倘若问几个比较戏剧性的问题,发现自己还是第一时间无法给出正确答案的,所以今天,系统性的整理一下有关slice的一些知识点。上面的示例输出是:从输出看,一般情况下,会有两个疑问:
使用了很多的slice,最近再准备面试的时候,才发现,自己对他是一知半解的,倘若问几个比较戏剧性的问题,发现自己还是第一时间无法给出正确答案的,所以今天,系统性的整理一下有关slice的一些知识点。
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 } 复制代码
上面的示例输出是:
[19 0 0 0 0 0 0 0 0 0 1 2] [19 0 0 0 0 0 0 0 0 0 1 2] 复制代码
从输出看,一般情况下,会有两个疑问:
- 我实例化一个切片之后,append两个元素,为什么不是切片的第一、二个元素
- 我一个值传递,调用FuncA,为啥可以在它函数体内,修改我切片的内容
有问题再洗洗看,就明白了切片的原理, 首先看第一个问题。实例化切片后,进行append操作
当我们在执行 make([]int, 10)
这样的语句时,底层调用的是 makeslice
函数。
0x002f 00047 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) LEAQ type.int(SB), AX 0x0036 00054 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) PCDATA $2, $0 0x0036 00054 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ AX, (SP) 0x003a 00058 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ $10, 8(SP) 0x0043 00067 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ $10, 16(SP) 0x004c 00076 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) CALL runtime.makeslice(SB) 复制代码
makeslice
函数的三个参数为, type.int
, 10
, 10
后面两个参数是slice的长度和底层数组的长度,即slice容量。
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) } 复制代码
makeslice
首先做的是检查栈溢出,如果溢出,直接 panic
,否则,调用 mallocgc
进行资源分配,看一下该函数的原型
func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer 复制代码
分配一个大小为size的对象。小对象是从per-P缓存的空闲列表中分配的。大对象(> 32 kB)是从堆中直接分配的。 mallocgc
的参数为,要分配的内存大小: mem= type.int.size * cap
。第二个参数为元素类型。第三个参数是个bool值,如果needzero为true,则返回范围的内存将归零。该方法的返回值是分配的资源的地址。 上面的动作完成之后,就是变量赋值了
0x004c 00076 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) CALL runtime.makeslice(SB) 0x0051 00081 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) PCDATA $2, $1 0x0051 00081 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ 24(SP), AX 0x0056 00086 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ AX, "".a+112(SP) 0x005b 00091 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ $10, "".a+120(SP) 0x0064 00100 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ $10, "".a+128(SP) 复制代码
该赋值动作涵盖三部分,第一部分就是分配的内存地址,第二部分就是slice长度,第三部分就是底层数组的长度,这也印证了,slice的数据类型由三部分组成。
在调用函数append进行增加元素的时候,我们看看slice又做了哪些操作
0x0070 00112 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) JMP 114 0x0072 00114 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $2, $2 0x0072 00114 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) LEAQ type.int(SB), CX 0x0079 00121 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $2, $1 0x0079 00121 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ CX, (SP) 0x007d 00125 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $2, $0 0x007d 00125 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ AX, 8(SP) 0x0082 00130 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ $10, 16(SP) 0x008b 00139 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ $10, 24(SP) 0x0094 00148 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ $12, 32(SP) 0x009d 00157 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) CALL runtime.growslice(SB) 0x00a2 00162 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $2, $1 0x00a2 00162 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ 40(SP), AX 0x00a7 00167 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ 48(SP), CX 0x00ac 00172 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ 56(SP), DX 0x00b1 00177 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) ADDQ $2, CX 0x00b5 00181 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) JMP 183 0x00b7 00183 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ $1, 80(AX) 0x00bf 00191 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ $2, 88(AX) 0x00c7 00199 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $0, $1 0x00c7 00199 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ AX, "".a+112(SP) 0x00cc 00204 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ CX, "".a+120(SP) 0x00d1 00209 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ DX, "".a+128(SP) 复制代码
我们发现,在增加元素之前,先对slice进行了一次扩容,调用了 runtime.growslice
函数,该函数原型是
func growslice(et *_type, old slice, cap int) slice
该函数提供了三个参数,第一个参数是元素类型 type.int
,第二个参数是扩容前原始slice,第三个参数是新slice的容量,该例子中是12.该函数调用完成后,返回新的slice. 新的slice进行了一个长度增加2的动作后,把新的元素放到了slice中数组中是放在偏移量为80和88的地址里的。
0x00b7 00183 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ $1, 80(AX) 0x00bf 00191 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ $2, 88(AX) 复制代码
这也就是第一个问题,其将数据是追加到数组的最后的。
所有动作完成之后,又重新进行了一次赋值操作
0x00c7 00199 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ AX, "".a+112(SP) 0x00cc 00204 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ CX, "".a+120(SP) 0x00d1 00209 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ DX, "".a+128(SP) 复制代码
之后就开始了 FuncA
函数的调用
0x00d9 00217 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:12) MOVQ AX, (SP) 0x00dd 00221 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:12) MOVQ CX, 8(SP) 0x00e2 00226 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:12) MOVQ DX, 16(SP) 0x00e7 00231 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:12) CALL "".FuncA(SB) 复制代码
此次调用非常有意思的是,参数上,将a slice的底层切片结构提供给了 FuncA
,这也就印证了第二个问题,为啥我在 FuncA
中对slice的元素修改,可以影响到我的原始slice. 再看一下 FuncA
的函数调用情况
"".FuncA STEXT nosplit size=50 args=0x18 locals=0x8 0x0000 00000 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:19) TEXT "".FuncA(SB), NOSPLIT|ABIInternal, $8-24 0x0000 00000 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:19) SUBQ $8, SP 0x0004 00004 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:19) MOVQ BP, (SP) 0x0008 00008 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:19) LEAQ (SP), BP 0x000c 00012 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:19) FUNCDATA $0, gclocals·1a65e721a2ccc325b382662e7ffee780(SB) 0x000c 00012 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:19) FUNCDATA $1, gclocals·69c1753bd5f81501d95132d08af04464(SB) 0x000c 00012 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:19) FUNCDATA $3, gclocals·9fb7f0986f647f17cb53dda1484e0f7a(SB) 0x000c 00012 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:20) PCDATA $2, $1 0x000c 00012 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:20) PCDATA $0, $0 0x000c 00012 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:20) MOVQ "".b+16(SP), AX 0x0011 00017 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:20) PCDATA $0, $1 0x0011 00017 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:20) CMPQ "".b+24(SP), $0 0x0017 00023 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:20) JHI 27 0x0019 00025 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:20) JMP 43 0x001b 00027 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:20) PCDATA $2, $0 0x001b 00027 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:20) MOVQ $19, (AX) 0x0022 00034 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:21) MOVQ (SP), BP 0x0026 00038 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:21) ADDQ $8, SP 0x002a 00042 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:21) RET 0x002b 00043 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:20) CALL runtime.panicindex(SB) 0x0030 00048 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/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+0 复制代码
首先进行一个索引的比较,如果是0,则执行赋值。然后收回资源返回。
再来看看几个有意思的示例:
package main import ( "fmt" ) func main() { a := make([]int, 10) FuncA(a) fmt.Println(a) } func FuncA(b []int) { b = append(b, 1, 2) } 复制代码
还是相同的例子,只不过,我们在 FuncA
中执行的是append操作,而不是索引的赋值操作。首先看一下该程序的输出:
[0 0 0 0 0 0 0 0 0 0] 复制代码
发现么,原始slice的值并没有修改,这特么的为啥,不是可以修改么?
0x0021 00033 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ "".b+96(SP), AX 0x0026 00038 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) LEAQ 2(AX), CX 0x002a 00042 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $2, $1 0x002a 00042 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ "".b+88(SP), DX 0x002f 00047 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $0, $1 0x002f 00047 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ "".b+104(SP), BX 0x0034 00052 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) CMPQ CX, BX 0x0037 00055 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) JLS 59 0x0039 00057 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) JMP 103 0x003b 00059 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $2, $-2 0x003b 00059 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $0, $-2 0x003b 00059 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) JMP 61 0x003d 00061 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $2, $1 0x003d 00061 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $0, $1 0x003d 00061 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ $1, (DX)(AX*8) 0x0045 00069 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ $2, 8(DX)(AX*8) 0x004e 00078 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $2, $0 0x004e 00078 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ DX, "".b+88(SP) 0x0053 00083 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ CX, "".b+96(SP) 0x0058 00088 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ BX, "".b+104(SP) 0x005d 00093 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:12) MOVQ 72(SP), BP 0x0062 00098 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:12) ADDQ $80, SP 0x0066 00102 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:12) RET 0x0067 00103 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $2, $1 0x0067 00103 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ AX, ""..autotmp_1+64(SP) 0x006c 00108 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $2, $2 0x006c 00108 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) LEAQ type.int(SB), SI 0x0073 00115 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $2, $1 0x0073 00115 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ SI, (SP) 0x0077 00119 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $2, $0 0x0077 00119 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ DX, 8(SP) 0x007c 00124 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ AX, 16(SP) 0x0081 00129 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ BX, 24(SP) 0x0086 00134 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ CX, 32(SP) 0x008b 00139 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) CALL runtime.growslice(SB) 0x0090 00144 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $2, $1 0x0090 00144 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ 40(SP), DX 0x0095 00149 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ 48(SP), AX 0x009a 00154 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ 56(SP), BX 0x009f 00159 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) LEAQ 2(AX), CX 0x00a3 00163 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ ""..autotmp_1+64(SP), AX 0x00a8 00168 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) JMP 61 复制代码
首先判断是否需要growslice,如果需要,先进行growslice操作,之后再进行元素的追加,元素的追加也是很简单的,就是寄存器的地址运算,然后将值移动到指定的。
0x003d 00061 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ $1, (DX)(AX*8) 0x0045 00069 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ $2, 8(DX)(AX*8) 复制代码
完成后进行赋值操作
0x004e 00078 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ DX, "".b+88(SP) 0x0053 00083 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ CX, "".b+96(SP) 0x0058 00088 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ BX, "".b+104(SP) 复制代码
上面的这个函数的操作,是在扩容的情况下,新分配的底层数组DX寄存器,+AX寄存器的偏移后,进行的赋值,此时b作为独立的slice,值是放到该slice中的底层数组中的。至于 FuncA
函数返回后,对于原始的slice就并没有产生什么影响。 下面的示例更能说明情况
package main import ( "fmt" ) func main() { a := make([]int, 10, 10) b := a b = append(b ,1,2) b[0] =19 fmt.Println(a) } 复制代码
结果是 [0 0 0 0 0 0 0 0 0 0]
.append在操作时,会判断,是否需要扩容,就是其cap(底层数组的长度)是否够用.如果不够用,进行了扩容的操作,那么会分配一个新的基础数组,那么b和a就没了联系,并不会再共用同一个底层数组,但是如果并没有进行扩容操作,底层数组够用,那么其实他们还是会共用同一个底层数组,只不过其所看到的内容不同罢了。
上面的例子还是比较极端的情况,再看一个不用进行growslice操作的情况,看看会不会有什么影响;
package main func main() { a := make([]int, 10, 20) FuncA(a) } func FuncA(b []int) { b = append(b, 1, 2) } 复制代码
首先看一下其输出情况:
[0 0 0 0 0 0 0 0 0 0] 复制代码
奇怪,我分配了那么大cap的slice,在 FuncA
中,并不需要进行growslice操作,为什么还是没有影响到原始的slice呢 .我们有理由怀疑,这一切的原因都是append函数,导致的,那么append到底进行了什么操作呢?
append函数是golang内建的函数,具体声明为:
// The append built-in function appends elements to the end of a slice. If // it has sufficient capacity, the destination is resliced to accommodate the // new elements. If it does not, a new underlying array will be allocated. // Append returns the updated slice. It is therefore necessary to store the // result of append, often in the variable holding the slice itself: // slice = append(slice, elem1, elem2) // slice = append(slice, anotherSlice...) // As a special case, it is legal to append a string to a byte slice, like this: // slice = append([]byte("hello "), "world"...) func append(slice []Type, elems ...Type) []Type 复制代码
就是说,内建的append函数将元素追加到slice尾部,如果其有足够的空间,因此可以元素追加到目标切片中,以容纳新元素。 如果没有,将分配一个新的基础数组。 追加返回更新的切片。 因此,有必要将append的结果存储在通常包含切片本身的变量中,
slice = append(slice, elem1, elem2) slice = append(slice, anotherSlice...) 复制代码
具体到,更简单的操作,来看一下:
package main import ( "fmt" ) func main() { a := make([]int, 10, 20) b := a b = append(b ,1,2) fmt.Println(a) } 复制代码
其结果一样的,输出是 [0 0 0 0 0 0 0 0 0 0]
但是通过b可以实现对a slice底层数组的索引修改,比如
package main import ( "fmt" ) func main() { a := make([]int, 10, 20) b := a b = append(b ,1,2) b[0] =19 fmt.Println(a) } 复制代码
输出是: [19 0 0 0 0 0 0 0 0 0]
.其底层数组中,指定是同一个数组,只是append的操作,并不影响a slice罢了。 a和b仅仅共用其相同的部分,其追加的东西并不会共享。
还有一种比较有意思的情况
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 } } 复制代码
其结果输出是: [0 0 0 0 0 0 0 0 0 0]
"".FuncA STEXT nosplit size=139 args=0x18 locals=0x40 0x0000 00000 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:9) TEXT "".FuncA(SB), NOSPLIT|ABIInternal, $64-24 0x0000 00000 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:9) SUBQ $64, SP 0x0004 00004 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:9) MOVQ BP, 56(SP) 0x0009 00009 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:9) LEAQ 56(SP), BP 0x000e 00014 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:9) FUNCDATA $0, gclocals·2d7c1615616d4cf40d01b3385155ed6e(SB) 0x000e 00014 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:9) FUNCDATA $1, gclocals·6d81f9fc90b2254ac2f1067a7bf2c67c(SB) 0x000e 00014 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:9) FUNCDATA $3, gclocals·db688afbc90e26183a53c9ad23b80c29(SB) 0x000e 00014 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) PCDATA $2, $0 0x000e 00014 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) PCDATA $0, $0 0x000e 00014 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ "".b+88(SP), AX 0x0013 00019 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ "".b+80(SP), CX 0x0018 00024 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) PCDATA $2, $1 0x0018 00024 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) PCDATA $0, $1 0x0018 00024 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ "".b+72(SP), DX 0x001d 00029 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) PCDATA $2, $0 0x001d 00029 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) PCDATA $0, $2 0x001d 00029 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ DX, ""..autotmp_2+32(SP) 0x0022 00034 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ CX, ""..autotmp_2+40(SP) 0x0027 00039 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ AX, ""..autotmp_2+48(SP) 0x002c 00044 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ $0, ""..autotmp_3+24(SP) 0x0035 00053 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ ""..autotmp_2+40(SP), AX 0x003a 00058 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ AX, ""..autotmp_4+16(SP) 0x003f 00063 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) JMP 65 0x0041 00065 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ ""..autotmp_4+16(SP), AX 0x0046 00070 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) CMPQ ""..autotmp_3+24(SP), AX 0x004b 00075 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) JLT 79 0x004d 00077 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) JMP 129 0x004f 00079 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ ""..autotmp_3+24(SP), AX 0x0054 00084 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) SHLQ $3, AX 0x0058 00088 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) PCDATA $2, $2 0x0058 00088 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) ADDQ ""..autotmp_2+32(SP), AX 0x005d 00093 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) PCDATA $2, $0 0x005d 00093 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ (AX), AX 0x0060 00096 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ AX, ""..autotmp_5+8(SP) 0x0065 00101 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ AX, "".v(SP) 0x0069 00105 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) INCQ AX 0x006c 00108 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ AX, "".v(SP) 0x0070 00112 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) JMP 114 0x0072 00114 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ ""..autotmp_3+24(SP), AX 0x0077 00119 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) INCQ AX 0x007a 00122 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ AX, ""..autotmp_3+24(SP) 0x007f 00127 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/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..@. 复制代码
如果改成如下形式,结果就不一样了:
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 } } 复制代码
其结果输出是:[1 1 1 1 1 1 1 1 1 1]
"".FuncA STEXT nosplit size=135 args=0x18 locals=0x20 0x0000 00000 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:9) TEXT "".FuncA(SB), NOSPLIT|ABIInternal, $32-24 0x0000 00000 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:9) SUBQ $32, SP 0x0004 00004 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:9) MOVQ BP, 24(SP) 0x0009 00009 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:9) LEAQ 24(SP), BP 0x000e 00014 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:9) FUNCDATA $0, gclocals·1a65e721a2ccc325b382662e7ffee780(SB) 0x000e 00014 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:9) FUNCDATA $1, gclocals·69c1753bd5f81501d95132d08af04464(SB) 0x000e 00014 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:9) FUNCDATA $3, gclocals·7cae486b9f11463edb9d0e91d30ff0f7(SB) 0x000e 00014 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) PCDATA $2, $0 0x000e 00014 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) PCDATA $0, $0 0x000e 00014 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ $0, ""..autotmp_2+16(SP) 0x0017 00023 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ "".b+48(SP), AX 0x001c 00028 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ AX, ""..autotmp_3+8(SP) 0x0021 00033 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) JMP 35 0x0023 00035 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ ""..autotmp_3+8(SP), AX 0x0028 00040 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) CMPQ ""..autotmp_2+16(SP), AX 0x002d 00045 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) JLT 49 0x002f 00047 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) JMP 118 0x0031 00049 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ ""..autotmp_2+16(SP), AX 0x0036 00054 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ AX, "".i(SP) 0x003a 00058 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $2, $1 0x003a 00058 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ "".b+40(SP), CX 0x003f 00063 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) CMPQ "".b+48(SP), AX 0x0044 00068 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) JHI 72 0x0046 00070 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) JMP 116 0x0048 00072 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $2, $0 0x0048 00072 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ (CX)(AX*8), CX 0x004c 00076 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $2, $2 0x004c 00076 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ "".b+40(SP), DX 0x0051 00081 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) INCQ CX 0x0054 00084 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) CMPQ "".b+48(SP), AX 0x0059 00089 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) JHI 93 0x005b 00091 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) JMP 114 0x005d 00093 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $2, $0 0x005d 00093 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) MOVQ CX, (DX)(AX*8) 0x0061 00097 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) JMP 99 0x0063 00099 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ ""..autotmp_2+16(SP), AX 0x0068 00104 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) INCQ AX 0x006b 00107 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) MOVQ AX, ""..autotmp_2+16(SP) 0x0070 00112 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10) JMP 35 0x0072 00114 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $2, $-2 0x0072 00114 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $0, $-2 0x0072 00114 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) JMP 128 0x0074 00116 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/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 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $2, $0 0x0080 00128 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) PCDATA $0, $1 0x0080 00128 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11) CALL runtime.panicindex(SB) 0x0085 00133 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/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+0 复制代码
总结:
1.append操作在无需扩容的情况下,新的slice和老slice共用底层的数组,通过索引对新的slice的修改,会影响到老的slice
2.所谓共用底层数组,仅仅共用其公共部分,至于特有的部分,各方也是无法修改和查看的 3.在for循环遍历slice时,value是一次值copy,对其的修改,并不会影响到slice底层的数据
欢迎关注我们的微信公众号,每天学习 Go 知识
以上所述就是小编给大家介绍的《我可能并不会使用golang slice》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- WhatsApp 的安全漏洞可能不会影响到普通人
- 恕我直言你可能真的不会java第9篇-Stream元素的匹配与查找
- 恕我直言你可能真的不会java第6篇:Stream性能差?不要人云亦云
- C# 永远不会返回的方法真的不会返回
- “Oracle 不会放弃 Java!”
- 还学不会webpack?看这篇
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Think Python
Allen B. Downey / O'Reilly Media / 2012-8-23 / GBP 29.99
Think Python is an introduction to Python programming for students with no programming experience. It starts with the most basic concepts of programming, and is carefully designed to define all terms ......一起来看看 《Think Python》 这本书的介绍吧!