Cha*_*Sun 10 arrays for-loop append go slice
我有这个简单的代码:
import "fmt"
type Foo struct {
val int
}
func main() {
var a = make([]*Foo, 1)
a[0] = &Foo{0}
var b = [3]Foo{Foo{1}, Foo{2}, Foo{3}}
for _, e := range b {
a = append(a, &e)
}
for _, e := range a {
fmt.Printf("%v ", *e)
}
}
Run Code Online (Sandbox Code Playgroud)
我期待它打印{0} {1} {2} {3},但它打印{0} {3} {3} {3}.这里发生了什么?
icz*_*cza 12
这是因为在for循环中,您使用副本而不是切片/数组元素本身.
它for ... range会复制它循环的元素,并附加这个临时循环变量的地址 - 这在所有迭代中都是相同的.所以你添加相同的指针3次.这个临时变量将Foo{3}在最后一次迭代中设置为(数组的最后一个元素),这就是为什么你看到打印3次的原因.
修复:不要添加循环变量的地址,而是添加数组元素的地址:
for i := range b {
a = append(a, &b[i])
}
Run Code Online (Sandbox Code Playgroud)
输出(在Go Playground上试试):
{0} {1} {2} {3}
Run Code Online (Sandbox Code Playgroud)
请参阅可能重复的已分配指针字段变为<nil>.
在Go中有指针类型和非指针类型,但没有"引用"(意思是它在C++和Java中使用).鉴于Go中没有"引用"类型,这不是意外行为.循环变量只是一个"普通"局部变量,它只能保存一个值(可能是指针或非指针),而不是一个引用.
摘自这个答案:
指针的价值就像让我们说
int数字一样.不同之处在于对该值的解释:指针被解释为内存地址,ints被解释为整数.当要改变类型的变量的值
int,则通过一个指向int它的类型的*int,并且修改尖锐的物体:*i = newvalue(分配值是一个int).也是一样的指针:当要改变指针类型的变量的值
*int,则通过一个指向*int它的类型的**int和修改尖锐的物体:*i = &newvalue(分配值是一个*int).
总而言之,循环变量只是一个普通变量,它具有您循环的数组/切片的元素类型,并且为了具有实际迭代的值,必须将值赋值给它复制值.它会在下一次迭代中被覆盖.
| 归档时间: |
|
| 查看次数: |
1372 次 |
| 最近记录: |