您的位置 首页 golang

我可能并不会使用golang 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)LEAQtype.int(SB), AX0x0036 00054 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)PCDATA$2, $00x0036 00054 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)MOVQAX, (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)CALLruntime.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)CALLruntime.makeslice(SB)0x0051 00081 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)PCDATA$2, $10x0051 00081 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)MOVQ24(SP), AX0x0056 00086 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)MOVQAX, "".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)JMP1140x0072 00114 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)PCDATA$2, $20x0072 00114 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)LEAQtype.int(SB), CX0x0079 00121 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)PCDATA$2, $10x0079 00121 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQCX, (SP)0x007d 00125 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)PCDATA$2, $00x007d 00125 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQAX, 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)CALLruntime.growslice(SB)0x00a2 00162 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)PCDATA$2, $10x00a2 00162 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQ40(SP), AX0x00a7 00167 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQ48(SP), CX0x00ac 00172 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQ56(SP), DX0x00b1 00177 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)ADDQ$2, CX0x00b5 00181 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)JMP1830x00b7 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, $10x00c7 00199 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQAX, "".a+112(SP)0x00cc 00204 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQCX, "".a+120(SP)0x00d1 00209 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQDX, "".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)MOVQAX, "".a+112(SP)0x00cc 00204 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQCX, "".a+120(SP)0x00d1 00209 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQDX, "".a+128(SP)复制代码

之后就开始了FuncA函数的调用

    0x00d9 00217 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:12)MOVQAX, (SP)0x00dd 00221 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:12)MOVQCX, 8(SP)0x00e2 00226 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:12)MOVQDX, 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=0x80x0000 00000 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:19)TEXT"".FuncA(SB), NOSPLIT|ABIInternal, $8-240x0000 00000 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:19)SUBQ$8, SP0x0004 00004 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:19)MOVQBP, (SP)0x0008 00008 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:19)LEAQ(SP), BP0x000c 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, $10x000c 00012 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:20)PCDATA$0, $00x000c 00012 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:20)MOVQ"".b+16(SP), AX0x0011 00017 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:20)PCDATA$0, $10x0011 00017 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:20)CMPQ"".b+24(SP), $00x0017 00023 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:20)JHI270x0019 00025 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:20)JMP430x001b 00027 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:20)PCDATA$2, $00x001b 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), BP0x0026 00038 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:21)ADDQ$8, SP0x002a 00042 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:21)RET0x002b 00043 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:20)CALLruntime.panicindex(SB)0x0030 00048 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:20)UNDEF0x0000 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 mainimport ("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), AX0x0026 00038 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)LEAQ2(AX), CX0x002a 00042 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)PCDATA$2, $10x002a 00042 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQ"".b+88(SP), DX0x002f 00047 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)PCDATA$0, $10x002f 00047 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQ"".b+104(SP), BX0x0034 00052 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)CMPQCX, BX0x0037 00055 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)JLS590x0039 00057 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)JMP1030x003b 00059 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)PCDATA$2, $-20x003b 00059 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)PCDATA$0, $-20x003b 00059 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)JMP610x003d 00061 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)PCDATA$2, $10x003d 00061 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)PCDATA$0, $10x003d 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, $00x004e 00078 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQDX, "".b+88(SP)0x0053 00083 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQCX, "".b+96(SP)0x0058 00088 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQBX, "".b+104(SP)0x005d 00093 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:12)MOVQ72(SP), BP0x0062 00098 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:12)ADDQ$80, SP0x0066 00102 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:12)RET0x0067 00103 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)PCDATA$2, $10x0067 00103 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQAX, ""..autotmp_1+64(SP)0x006c 00108 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)PCDATA$2, $20x006c 00108 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)LEAQtype.int(SB), SI0x0073 00115 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)PCDATA$2, $10x0073 00115 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQSI, (SP)0x0077 00119 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)PCDATA$2, $00x0077 00119 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQDX, 8(SP)0x007c 00124 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQAX, 16(SP)0x0081 00129 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQBX, 24(SP)0x0086 00134 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQCX, 32(SP)0x008b 00139 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)CALLruntime.growslice(SB)0x0090 00144 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)PCDATA$2, $10x0090 00144 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQ40(SP), DX0x0095 00149 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQ48(SP), AX0x009a 00154 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQ56(SP), BX0x009f 00159 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)LEAQ2(AX), CX0x00a3 00163 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQ""..autotmp_1+64(SP), AX0x00a8 00168 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)JMP61复制代码

首先判断是否需要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)MOVQDX, "".b+88(SP)0x0053 00083 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQCX, "".b+96(SP)0x0058 00088 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQBX, "".b+104(SP)复制代码

上面的这个函数的操作,是在扩容的情况下,新分配的底层数组DX寄存器,+AX寄存器的偏移后,进行的赋值,此时b作为独立的slice,值是放到该slice中的底层数组中的。至于FuncA函数返回后,对于原始的slice就并没有产生什么影响。下面的示例更能说明情况

package mainimport ("fmt")func main() {a := make([]int, 10, 10)b := ab = append(b ,1,2)b[0] =19fmt.Println(a)}复制代码

结果是[0 0 0 0 0 0 0 0 0 0].append在操作时,会判断,是否需要扩容,就是其cap(底层数组的长度)是否够用.如果不够用,进行了扩容的操作,那么会分配一个新的基础数组,那么b和a就没了联系,并不会再共用同一个底层数组,但是如果并没有进行扩容操作,底层数组够用,那么其实他们还是会共用同一个底层数组,只不过其所看到的内容不同罢了。

上面的例子还是比较极端的情况,再看一个不用进行growslice操作的情况,看看会不会有什么影响;

package mainfunc 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 mainimport ("fmt")func main() {a := make([]int, 10, 20)b := ab = append(b ,1,2)fmt.Println(a)}复制代码

其结果一样的,输出是[0 0 0 0 0 0 0 0 0 0]

但是通过b可以实现对a slice底层数组的索引修改,比如

package mainimport ("fmt")func main() {a := make([]int, 10, 20)b := ab = append(b ,1,2)b[0] =19fmt.Println(a)}复制代码

输出是:[19 0 0 0 0 0 0 0 0 0].其底层数组中,指定是同一个数组,只是append的操作,并不影响a slice罢了。a和b仅仅共用其相同的部分,其追加的东西并不会共享。

还有一种比较有意思的情况

package mainimport ("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=0x400x0000 00000 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:9)TEXT"".FuncA(SB), NOSPLIT|ABIInternal, $64-240x0000 00000 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:9)SUBQ$64, SP0x0004 00004 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:9)MOVQBP, 56(SP)0x0009 00009 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:9)LEAQ56(SP), BP0x000e 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, $00x000e 00014 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)PCDATA$0, $00x000e 00014 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)MOVQ"".b+88(SP), AX0x0013 00019 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)MOVQ"".b+80(SP), CX0x0018 00024 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)PCDATA$2, $10x0018 00024 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)PCDATA$0, $10x0018 00024 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)MOVQ"".b+72(SP), DX0x001d 00029 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)PCDATA$2, $00x001d 00029 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)PCDATA$0, $20x001d 00029 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)MOVQDX, ""..autotmp_2+32(SP)0x0022 00034 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)MOVQCX, ""..autotmp_2+40(SP)0x0027 00039 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)MOVQAX, ""..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), AX0x003a 00058 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)MOVQAX, ""..autotmp_4+16(SP)0x003f 00063 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)JMP650x0041 00065 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)MOVQ""..autotmp_4+16(SP), AX0x0046 00070 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)CMPQ""..autotmp_3+24(SP), AX0x004b 00075 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)JLT790x004d 00077 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)JMP1290x004f 00079 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)MOVQ""..autotmp_3+24(SP), AX0x0054 00084 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)SHLQ$3, AX0x0058 00088 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)PCDATA$2, $20x0058 00088 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)ADDQ""..autotmp_2+32(SP), AX0x005d 00093 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)PCDATA$2, $00x005d 00093 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)MOVQ(AX), AX0x0060 00096 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)MOVQAX, ""..autotmp_5+8(SP)0x0065 00101 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)MOVQAX, "".v(SP)0x0069 00105 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)INCQAX0x006c 00108 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQAX, "".v(SP)0x0070 00112 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)JMP1140x0072 00114 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)MOVQ""..autotmp_3+24(SP), AX0x0077 00119 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)INCQAX0x007a 00122 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)MOVQAX, ""..autotmp_3+24(SP)0x007f 00127 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)JMP650x0081 00129 (<unknown line number>)PCDATA$0, $10x0081 00129 (<unknown line number>)MOVQ56(SP), BP0x0086 00134 (<unknown line number>)ADDQ$64, SP0x008a 00138 (<unknown line number>)RET0x0000 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.T0x0020 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$.|..2H0x0050 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 mainimport ("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=0x200x0000 00000 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:9)TEXT"".FuncA(SB), NOSPLIT|ABIInternal, $32-240x0000 00000 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:9)SUBQ$32, SP0x0004 00004 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:9)MOVQBP, 24(SP)0x0009 00009 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:9)LEAQ24(SP), BP0x000e 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, $00x000e 00014 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)PCDATA$0, $00x000e 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), AX0x001c 00028 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)MOVQAX, ""..autotmp_3+8(SP)0x0021 00033 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)JMP350x0023 00035 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)MOVQ""..autotmp_3+8(SP), AX0x0028 00040 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)CMPQ""..autotmp_2+16(SP), AX0x002d 00045 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)JLT490x002f 00047 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)JMP1180x0031 00049 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)MOVQ""..autotmp_2+16(SP), AX0x0036 00054 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)MOVQAX, "".i(SP)0x003a 00058 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)PCDATA$2, $10x003a 00058 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQ"".b+40(SP), CX0x003f 00063 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)CMPQ"".b+48(SP), AX0x0044 00068 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)JHI720x0046 00070 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)JMP1160x0048 00072 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)PCDATA$2, $00x0048 00072 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQ(CX)(AX*8), CX0x004c 00076 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)PCDATA$2, $20x004c 00076 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQ"".b+40(SP), DX0x0051 00081 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)INCQCX0x0054 00084 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)CMPQ"".b+48(SP), AX0x0059 00089 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)JHI930x005b 00091 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)JMP1140x005d 00093 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)PCDATA$2, $00x005d 00093 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)MOVQCX, (DX)(AX*8)0x0061 00097 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)JMP990x0063 00099 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)MOVQ""..autotmp_2+16(SP), AX0x0068 00104 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)INCQAX0x006b 00107 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)MOVQAX, ""..autotmp_2+16(SP)0x0070 00112 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:10)JMP350x0072 00114 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)PCDATA$2, $-20x0072 00114 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)PCDATA$0, $-20x0072 00114 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)JMP1280x0074 00116 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)JMP1280x0076 00118 (<unknown line number>)MOVQ24(SP), BP0x007b 00123 (<unknown line number>)ADDQ$32, SP0x007f 00127 (<unknown line number>)RET0x0080 00128 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)PCDATA$2, $00x0080 00128 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)PCDATA$0, $10x0080 00128 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)CALLruntime.panicindex(SB)0x0085 00133 (/Users/zhaojunwei/workspace/src/just.for.test/sour_slicetest/main2.go:11)UNDEF0x0000 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$(H0x0040 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底层的数据


文章来源:智云一二三科技

文章标题:我可能并不会使用golang slice

文章地址:https://www.zhihuclub.com/134.shtml

关于作者: 智云科技

热门文章

评论已关闭

4条评论

  1. The developmental and health benefits of breastfeeding should be considered along with the motherГў s clinical need for PLAQUENIL and any potential adverse effects on the breastfed child from PLAQUENIL or from the underlying maternal condition 6 years from first seeking help to reaching diagnosis, and 1

  2. Schedule an appointment today to determine what lenses are the best solution for your unique vision Plasma and tissue estrogen levels are described by their geometric means with 95 confidence intervals CI

  3. Finally, the NCT02626507 trial is a dose escalation phase Ib trial aimed to determine the toxicity, tolerability, and potential efficacy of gedatolisib an inhibitor of phosphatidylinositol 3 kinase PI3K and mammalian target of rapamycin mTOR pathway used in combination with palbociclib and fulvestrant as first treatment in 18 patients with newly diagnosed stage I to IV HR HER2 BC

网站地图