go - 分配给切片的值与指针
问题描述
我正在完成这个“Tour of Go”,我正在这里做这个练习。我最初是这样写的答案:
func Pic(dx, dy int) [][]uint8 {
outer := make([][]uint8, dy)
inner := make([]uint8, dx)
for y, _ := range outer {
for x, _ := range inner {
inner[x] = x^y // this is one of the image functions they give
}
outer[y] = inner
}
return outer
}
我认为这应该可行,但是当我运行时,Pic(5,5)
我得到:
[[0 4 8 12 16] [0 4 8 12 16] [0 4 8 12 16] [0 4 8 12 16] [0 4 8 12 16]]
不对,很明显。
所以,我终于发现我需要将我的inner := make([]uint8, dx)
声明移动到第一个循环中,如下所示:
func Pic(dx, dy int) [][]uint8 {
outer := make([][]uint8, dy)
for y, _ := range outer {
inner := make([]uint8, dx)
for x, _ := range inner {
inner[x] = x^y // this is one of the image functions they give
}
outer[y] = inner
}
return outer
}
现在Pic(5,5)
给我正确的答案:
[[0 0 0 0 0] [0 1 2 3 4] [0 2 4 6 8] [0 3 6 9 12] [0 4 8 12 16]]
这里发生了什么事?我认为这与指针或其他东西有关,但我想确定我真的了解发生了什么。显然,在第一个示例中,每次我将新的东西重新分配给之前分配给它们inner
的值时,它们也会发生变化。outer
inner
但是在第二个例子中会发生什么?每次我们通过range outer
循环时,inner
变量都会被重新声明,但是outer
之前inner
分配给它们的值会发生什么?它们现在是否以某种方式“被切断”并且仅作为副本存在?
我主要感到困惑,因为分配行在outer[y] = inner
这两个示例中都没有改变,所以我不明白其中一个分配值副本的机制,而在另一个分配中分配我认为的内容一个指针。
解决方案
在第一种情况下,您从未“将新的东西重新分配给inner
”。uint8
您创建了一个名为的切片inner
,并在其中填充了值(多次覆盖这些值),并使的每个元素都outer
包含 的副本inner
。但请记住,切片只是存在于某处的数组的视图(在您的情况下,支持数组是由匿名创建的make
)。复制切片不会复制数组中的值,它只是复制切片标头,这意味着现在有多个视图在同一个存储上(这很好,也很安全)。
在第二种情况下,您调用make
的每一行outer
,因此创建了五个不同的支持数组,inner
每次都指向不同的数组。这一次,当你分配inner
给 的一个元素时outer
,你得到了五个真正不同的切片头,而不是同一个的五个副本。
简而言之:切片是一个值,但它是一个包含指针的值。指针可能指向一个有名字的数组,也可能指向一个完全匿名的数组。没有什么可担心的;Go 将确保任何被指向的东西都保持活力。
推荐阅读
- python - NetworkX 中的最短路径生成器
- r - jsonlite 错误:词法错误:json 文本中的无效字符
- java - 在 bash shell 上使用 Maven 来自动化我的部署工作流程 (github-package-registry)
- geocoding - 当交叉路口包括州际高速公路时地理编码失败
- python - django.db.utils.OperationalError: no such table: Recruiter_jobs table not found 错误?
- node.js - NPM 找不到它认为缓存的文件(errno -4058 没有这样的文件或目录)
- smartcontracts - 意外的基板“ink_env::debug_println”行为
- reactjs - 如何设置材质顶部标签导航的样式?
- python - 在python中将数字舍入到最接近的000
- css - 我应该如何正确使用媒体查询?