使用以下代码:https://play.golang.org/p/tCm1W-K-6ob
此代码将打印:[c c c]
,但[a b c]
除外。
type A struct {
a *string
}
func f() {
slist := []string{"a", "b", "c"}
list := make([]*A, len(slist))
for i, v := range slist {
item := &A{
a: &v,
}
list[i] = item
}
fmt.Printf("[%s %s %s]", *list[0].a, *list[1].a, *list[2].a)
}
func main() {
f()
}
为什么列表不是["a", "b", "c"]
?范围或&string
发生了什么?
答案 0 :(得分:1)
https://play.golang.org/p/utJrUmxeqfh
size
package main
import (
"fmt"
)
func main() {
foo := []int{1, 2, 3}
for _, f := range foo {
fmt.Printf("value is %d, addr is %p \n", f, &f)
}
fmt.Println("Hello, playground")
}
value is 1, addr is 0x414020
value is 2, addr is 0x414020
value is 3, addr is 0x414020
Hello, playground
中的值f
具有相同的地址
答案 1 :(得分:1)
所有项都包含一个局部变量v
的地址。
如果您的目标是在a
字段中分配slice元素的地址,请执行以下操作:
for i := range slist {
item := &A{
a: &slist[i], // address of element instead of local variable.
}
list[i] = item
}
您还可以通过在每次循环迭代中创建一个新变量来获得所需的输出:
for i, v := range slist {
v := v // create new value on each iteration.
item := &A{
a: &v,
}
list[i] = item
}
答案 2 :(得分:0)
问题是迭代器变量仅分配一次,并且它指向的值在循环的每次迭代中都会更改:
package main
import (
"fmt"
)
type A struct {
a *string
}
func f() {
slist := []string{"a", "b", "c"}
list := make([]*A, len(slist))
// v is only allocated once and the value at it's address is changed
// on each iteration.
for i, v := range slist {
fmt.Printf("Iteration %d: address of v %#v, value of v \"%s\"\n", i+1, &v, v)
// Add in a temp variable, which will get allocated
// and hence have a new address each iteration.
t := v
// Now assign that temp variable's address to the Item's a.
list[i] = &A{
a: &t,
}
}
fmt.Printf("[%s %s %s]", *list[0].a, *list[1].a, *list[2].a)
}
func main() {
f()
}
但是,我强烈感觉这是不直观的,因为我们几乎都在谈论过早的优化。 (稍微简化了一下):Go中的字符串基本上是一个字节的切片([]byte
),其中一个切片已经是指向后备数组的指针。有关详细信息,请参见Go Slices: usage and internals。
答案 3 :(得分:-2)
您可以尝试
在这里,我可以运行您的代码并进行一些更改。
https://play.golang.org/p/GmU3goeOKdF
这是代码
package main
import (
"fmt"
)
type A struct {
a *string
}
func f() {
slist := []string{"a", "b", "c"}
list := make([]*A, len(slist))
for i, v := range slist {
item := &A{
a: &v,
}
list[i] = item
fmt.Printf("%s", *list[i].a)
}
}
func main() {
f()
}
输出 abc