Loops 指针和循环的切片
我想这个问题问了好几次,但我还是很困惑: 我有以下代码:Loops 指针和循环的切片,loops,pointers,go,slice,Loops,Pointers,Go,Slice,我想这个问题问了好几次,但我还是很困惑: 我有以下代码: type obj struct { s *string } var cmdsP = []*string { stringPointer("create"), stringPointer("delete"), stringPointer("update"), } var cmds = []string { "create", "delete", "update", } // []
type obj struct {
s *string
}
var cmdsP = []*string {
stringPointer("create"),
stringPointer("delete"),
stringPointer("update"),
}
var cmds = []string {
"create",
"delete",
"update",
}
// []*string
func loop1() {
slice := make([]obj, 0, 0)
for _, cmd := range cmdsP {
slice = append(slice, obj{cmd})
}
for _, o := range slice {
fmt.Println(*o.s)
}
}
// []string
func loop2() {
slice := make([]obj, 0, 0)
for _, cmd := range cmds {
slice = append(slice, obj{&cmd})
}
for _, o := range slice {
fmt.Println(*o.s)
}
}
func stringPointer(v string) *string {
return &v
}
唯一的区别在于slice semantic
[]*string
和[]string
如何改变cmd
变量的行为?您能详细地画出或解释一下在两个循环的迭代过程中内存中发生了什么吗 在集合上调用range
时,go运行时初始化2个内存位置;一个用于索引(在本例中为
),一个用于值cmd
然后,range所做的是获取集合中的每个项,并将它们复制到调用range
时创建的内存位置
这意味着片中的每个项都被逐个放入该内存位置
当您执行&cmd
时,您正在使用指针。该指针指向每个切片项要复制到的共享内存位置
使用&cmd
创建的所有指针都指向相同的内存位置
这意味着在范围
完成后,指针指向的内存位置中剩下的唯一值是范围
迭代中的最后一个值
这就是您获得输出的原因
update
update
update
这是因为在一种情况下,您将向struct传递地址,而在另一种情况下,您将传递字符串值。因此,每当您将结构字段附加到切片时,它都将更新同一地址上的现有值。这就是为什么您只得到结构的指针类型切片的最后一个值,在本例中是
update
// []string
func loop2() {
slice := make([]obj, 0, 0)
for _, cmd := range cmds {
slice = append(slice, obj{&cmd})
}
for _, o := range slice {
fmt.Println(*o.s)
}
}
&cmd
将指向同一地址,该地址在每次迭代中将其值更新到同一位置,而在loop1
中将地址传递给cmd
时,情况并非如此
已编辑
这是[]obj
的一个片段,它有一个指针类型*字符串的字段
slice := make([]obj, 0, 0)
因此,当您在其上循环时,实际上是在传递cmd
的地址,并将其分配给指针字段
要查看差异,请打印类型,您将获得例如的信息:
func loop1() {
slice := make([]string, 0, 0)
for _, cmd := range cmdsP {
slice = append(slice, *cmd)
}
for _, o := range slice {
fmt.Println(o)
}
fmt.Printf("%#v\n", slice)
}
在上面的例子中,您正在创建一段字符串
// []*string
func loop1() {
slice := make([]obj, 0, 0)
for _, cmd := range cmdsP {
slice = append(slice, obj{cmd})
}
for _, o := range slice {
fmt.Println(*o.s)
}
fmt.Printf("%#v\n", slice)
}
在第二种情况下,您正在创建一个obj
struct的切片,其中包含指向string
的指针字段。它们都是不同的情况。使用fmt
package查看在loop1
函数中创建的实际切片类型
谢谢您的回答!您说过
,所以每当您将结构字段附加到切片时
,但如果我附加字符串字段切片:=make([]string,0,0)
一切正常。有什么区别@请检查编辑后的答案