这道 reslice 的题 简单,但原理你知晓吗?

这道 reslice 的题 简单,但原理你知晓吗?

2 年前 · 来自专栏 golang 每日一题

package main
func a() []int {
 a1 := []int{3}
 a2 := a1[1:]
 return a2
func main() {

看到这个题, 你的第一反应是啥?

(A) 编译失败
(B) panic: runtime error: index out of range [1] with length 1
(C) []
(D) 其他

也许你的第一感觉是: 肯定能编译过, 但是运行时一定会panic的. 但事与愿违竟然能够正常运行, 结果是:[]

a1 和 a2 共享同样的底层数组, len(a1) = 1, a1[1]绝对会panic, 但是a[1:]却能正常输出, 这是为何?

解答

看下如下代码输出的结果是啥?

a1 := []int{3}
fmt.Printf("len:%d, cap:%d", len(a1), cap(a1))
fmt.Println("a[0:]", a1[0:])
fmt.Println("a[1:]", a1[1:])
fmt.Println("a[2:]", a1[2:])

输出:

len:1, cap:1
a[0:]: [1]
a[1:] []
panic: runtime error: slice bounds out of range [2:1]

看到这里是不是,已经有些端倪了

再看下汇编的执行情况

".a STEXT size=87 args=0x18 locals=0x18
	// 省略...
	0x0028 00040 (main.go:6)	CALL	runtime.newobject(SB)
	0x002d 00045 (main.go:6)	MOVQ	8(SP), AX  // 将slice的数据首地址加载到AX寄存器
	0x0032 00050 (main.go:6)	MOVQ	$3, (AX)   // 把3放入到AX寄存器中, 也就是a1[0]
	0x0039 00057 (main.go:8)	MOVQ	AX, "".~r0+32(SP)
	0x003e 00062 (main.go:8)	XORPS	X0, X0     // 初始化 X0 寄存器