返回博客

Go 语言切片:一个有趣的 append() 循环 bug

学习 Go 语言切片时遇到的一个有趣 bug:在循环中使用 append() 扩容切片时,循环条件使用 len(slice) 导致无限循环。文章分析了 bug 原因,并提供了修复方案,同时也用 JavaScript 复现了该问题。

Mt.r
|

我学到切片数组部分,想给数组扩个容。

改了一下示例代码,如下:

package main

import "fmt"

func main() {
	var arr1 [6]int
	var slice1 []int = arr1[2:5] // item at index 5 not included!

	// load the array with integers: 0,1,2,3,4,5
	for i := 0; i < len(arr1); i++ {
		arr1[i] = i
	}

	// print the slice
	for i := 0; i < len(slice1); i++ {
		fmt.Printf("Slice at %d is %d\n", i, slice1[i])
	}

	fmt.Printf("The length of arr1 is %d\n", len(arr1))
	fmt.Printf("The length of slice1 is %d , %p\n", len(slice1), &slice1)
	fmt.Printf("The capacity of slice1 is %d , %p\n", cap(slice1), &slice1)

	// grow the slice
	slice1 = slice1[:cap(slice1)]
	slice1Len := len(slice1)
	for i := 0; i < len(slice1)-1; i++ {
		slice1 = append(slice1, 1)
	}

	fmt.Printf("The length of slice1 is %d , %p\n", len(slice1), &slice1)
	fmt.Printf("The capacity of slice1 is %d , %p\n", cap(slice1), &slice1)

	// grow the slice beyond capacity
	//slice1 = slice1[0:7 ] // panic: runtime error: slice bound out of range
}

然后走到

for i := 0; i < len(slice1)-1; i++ {
  slice1 = append(slice1, 1)
}

这儿就无限套娃挂了。

后来改了一下

// grow the slice
slice1 = slice1[:cap(slice1)]
slice1Len := len(slice1)
for i := 0; i < slice1Len; i++ {
  fmt.Println(slice1Len, len(slice1))
  slice1 = append(slice1, 1)
}

就解决了,这个 bug 挺有意思的

然后我用 js 也复现了一下

let a = [1, 2, 3, 4];
function getLength(params) {
  return params.length;
}
for (let index = 0; index < getLength(a); index++) {
  console.log(`a.length`, a.length);
  a.push(1);
}

console.log('程序为啥不走了?');

太有趣了。