【发布时间】:2020-11-29 19:27:49
【问题描述】:
在使用切片时,我很难找到一个创建对索引表达式的引用是个好主意的好案例。
因为切片,通过内置函数append,是使用特定机制实现的,它们的支持数组可以在运行时修改,虽然这被认为是一件好事,但我下面的代码有一个不明显的错误。
但在下面的例子中,从编译器的角度来看这是完全正确的,这对大多数程序员来说是非常混乱的,但是,这是语言规范允许的。
package main
import (
"fmt"
)
func main() {
broken()
fmt.Printf("------------\n")
lessbroken()
}
func broken() {
var lump []int
var lumpp []*int
for i := 0; i < 8; i++ {
lump = append(lump, int(i))
lumpp = append(lumpp, &lump[i])
}
*(lumpp[0]) = 5
fmt.Printf("lump[0]: %#v\n", lump[0])
}
func lessbroken() {
lump := make([]int, 8, 8)
var lumpp []*int
for i := 0; i < 8; i++ {
lump[i] = i
lumpp = append(lumpp, &lump[i])
}
*(lumpp[0]) = 5
fmt.Printf("lump[0]: %#v\n", lump[0])
}
输出
lump[0]: 0
------------
lump[0]: 5
https://play.golang.org/p/rl5O9ecp7Zq
我很难理解Why does pointer assignment cause variable assignment to not always stick? 的帖子,现在我想弄清楚我是否应该将其视为不好的做法,或者是否有什么东西,我可能想念..
【问题讨论】:
-
“因为切片大多由运行时自动管理,所以它们的内存地址可以在运行时修改” 前件和后件都是错误的:切片都不是“由运行时管理”(至少不会更多)比 Go 中的任何其他变量)也不能它们的“地址......被修改”(因为没有变量的地址可以被修改)。在切片增长期间,一个 new 切片(可能会返回一个新地址和一个新的后备数组,但旧切片及其地址不变。
-
好的,精度是值得的。不过,当您说切片不以某种方式由运行时管理时,我仍然不相信。
-
这就像说int32变量由运行时管理。是的,它们在运行时为变量和 GC 提供内存的意义上说,它曾经无法访问,但因此它是非信息,因为对于 Go 中的所有内容都是如此:int32、complex126、chan uint8 和函数闭包命名为很少。切片并不比布尔更“由运行时管理”。
-
我认为罪魁祸首在
If the capacity of s is not large enough to fit the additional values, append allocates a new, sufficiently large underlying array that fits both the existing slice elements and the additional values. Otherwise, append re-uses the underlying array.。参考:golang.org/ref/spec#Appending_and_copying_slices 我说明的造成困难的“东西”是append内置函数。但是append是使用切片的方式,并且与这种类型密切相关。为了初步解决这个问题,我说没关系...... -
...用
slice这个词来概括。
标签: go