「Golang」遇到的有趣的Go赋值问题并附带以下不负责任的解析

今天在做一道题的时候发现了这么一个有趣的题目:

func main() {
	index := 1
	a := []string{"f", "ff", "fff"}
	index, a[index-1] = 88888, "ffff"
	fmt.Println(a)
}

这个输出是什么呢?我第一眼看的时候感觉会输出panic,因为下标超界,但是运行之后发现没这么简单,运行结果如下
在这里插入图片描述
运行之后我惊了,不知道为什么会这样,然后我就输出了汇编看了一下(去掉了一些多余的汇编代码,我们只看赋值那行的汇编):

本篇文章基于go1.15+版本以及mac os 操作系统

//把index的值复制到DX寄存器中
0x00f2 00242 MOVQ    "".index+48(SP), DX 
 // DX寄存器的值-1 在此能看出是先对其进行了-1
0x00f7 00247 DECQ    DX 
// 把DX寄存器里的值复制autotmp_4+56这个地址上
0x00fa 00250 MOVQ    DX, ""..autotmp_4+56(SP) 
// 把88888赋值给index+48地址即赋值88888给index
0x00ff 00255 MOVQ    $88888, "".index+48(SP)
// 把刚才-1了的值放在AX寄存器中
0x0108 00264 MOVQ    ""..autotmp_4+56(SP), AX
// 把a就是那个数组的偏移104个地址的值放入DX寄存器
0x010d 00269 MOVQ    "".a+104(SP), DX
// 把a就是那个数组的偏移112个地址的值放入DX寄存器
0x0112 00274 MOVQ    "".a+112(SP), CX
// 比较AX寄存器和CX寄存器 
0x0117 00279 CMPQ    AX, CX
// 如果没溢出就跳到293
0x011a 00282 JCS     293
// 否则
0x011c 00284 NOP
// 跳到605
0x0120 00288 JMP     605
// 逻辑移位(好像是)
0x0125 00293 SHLQ    $4, AX
// 把DX的AX*1的地址给CX Ax就是被-1后的那个值存放的地方
0x0129 00297 LEAQ    (DX)(AX*1), CX
0x012d 00301 LEAQ    8(CX), CX
0x0131 00305 MOVQ    $4, (CX)
// 反正就是之前做了一堆复制和传地址操作把DX的AX*1的地址给了DI
0x0138 00312 LEAQ    (DX)(AX*1), DI
·····
// 把ffff这个字符串放到AX寄存器内
0x014a 00330 LEAQ    go.string."ffff"(SB), AX
// 从AX寄存器复制出ffff复制到DI就是要修改的数组的那个位置
0x0151 00337 MOVQ    AX, (DI)

大概就是这样,其实最根本的原因就是

index-1这个操作早于给index赋值这个操作,并且提前将其放到了某块地址中所以后续的数组下标赋值操作是根据这个放在某个地址中的index-1的值进行的赋值。

总结一下:

这种多重赋值分为两个步骤,有先后顺序:
计算等号左边的索引表达式和取址表达式,接着计算等号右边的表达式

作者对汇编不甚了解,如果哪里有错误请大佬指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值