我能找到的最通用的错误版本如下所示:
package main
import "fmt"
func main() {
values := []any{1,2,3}
values = append(values[:1],values[1:])
fmt.Println(values)
}
这会导致堆栈溢出(有趣的是我在这个网站上发布)。如果我values
从打印语句中删除并将其替换为其他内容(例如0
),它不会引发错误并且可以正确打印。
如果我习惯于...
可变地使用追加,代码将正确运行并打印[1 2 3]
.
我还尝试将fmt.Println("This section of code reached successfully!")
更改放在更改values
和其他打印语句之间,但它在错误之前打印,这意味着这fmt.Println(values)
是导致溢出的行。
values
我可以单独打印第一个项目而不会出现错误,但是单独打印列表的第二个项目会导致溢出。
此版本的代码运行没有错误:
package main
import "fmt"
func main() {
values := append([]any{1},[]any{2,3})
fmt.Println(values)
}
为什么会出现这种情况?这是我在一个项目中遇到的错误的更普遍的版本。
2
4 个回答
4
切片不是数组,它们是数组的视图。这是一个简化的示例,用于说明:
values := []any{1, 2, 3}
slice := values[1:] // [2, 3]
values[1] = 100
fmt.Println(slice) // [100, 3]
如果更改数组的元素,其中的切片也会更改,反之亦然。
现在,当您将数组的切片附加到同一个数组时,您就会遇到自引用的问题。
values := []any{1,2,3}
values = append(values[:1],values[1:]) // [1, values[1:]]
values[1:]
是[values[1:]]
(因为它是 的实时视图values
,而不是[2, 3]
您假设的那样),这是[[values[1:]]]
…所以values
不是[1, 2, 3]
,但是[1, [[[[[[[[[[[[stackoverflow
请注意,结构本身很好,尽管不是您想要的。当您尝试打印它时,这只是一个错误,因为fmt.Println
不知道如何处理递归结构。
为了执行您想要的操作,您需要先复制切片,然后再附加它,这样您就不会最终将values
递归引用添加到values
.
5
-
如何复制切片?
– -
3如果你使用的是最新的 Go 版本(我认为它是在 1.22 中添加的)。否则,创建一个具有相同大小的新切片,并用于
copy
将旧切片中的所有元素复制到新切片。
–
-
1首先为要进入的元素分配一个新数组:
slicedValues := make([]any, len(values))
然后将元素复制到:(copy(slicedValues, values[1:])
如果不能Clone
)
–
-
和开始——它们应该让你了解数组和切片。
– -
1不过这并不重要,请将 ` // [9, 3]` 修改为 ` // [100, 3]`
–
|
您的追加语句将原始values
切片放入其自身中,创建递归数据结构。确保这种情况不会发生的唯一方法是创建一个新切片并将值复制到其中。
values := []any{1, 2, 3}
values = append(values[:1], slices.Clone(values[1:]))
fmt.Println(values)
结果是[1 [2 3]]
|
如果您始终需要第一个元素,然后需要子切片中的其余元素,那么这会更有效。它不会复制切片,而是创建一个新切片并用现有切片填充它。
values := []any{1, 2, 3}
values = append([]any{}, values[0], values[1:])
fmt.Println(values)
|
方法append()导致切片递归嵌套。
values := []any{1,2,3}
values = append(values[:1], values[1:])
fmt.Println(values)
在这里,当您将append()与values[1:]一起使用时,您试图将一个切片附加到values[:1],这会产生嵌套的切片结构。当您尝试打印值时,嵌套切片的递归最终会导致堆栈溢出。
一种解决方案是在附加之前复制切片:
values := []any{1, 2, 3}
sliceCopy := make([]any, len(values)-1)
copy(sliceCopy, values[1:])
values = append(values[:1], sliceCopy)
fmt.Println(values)
|
append
:append(values[:1],values[1:]...)
–
[1 [2 3]]
。–
|