切片指针和循环[重复]
Posted
技术标签:
【中文标题】切片指针和循环[重复]【英文标题】:Slice of pointers and loop [duplicate] 【发布时间】:2018-12-20 18:43:23 【问题描述】:我认为这个问题被问了好几次,但我仍然感到困惑:
我有以下代码:
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, objcmd)
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
https://play.golang.org/p/65Le_8Pi3Mi
唯一的区别在于切片语义[]*string
和[]string
它如何改变cmd
变量的行为?您能否详细说明或详细说明在通过两个循环进行迭代期间内存中发生的情况?
【问题讨论】:
【参考方案1】:当你在一个集合上调用 range
时,go 运行时会初始化 2 个内存位置;一个用于索引(在本例中为_
),一个用于值cmd
。
然后 range 的作用是获取集合中的每个项目,并将它们复制到它在您调用 range
时创建的内存位置。
这意味着切片中的每个项目都会被一个一个地放入该内存位置。
当您执行&cmd
时,您将获得一个指针。该指针指向每个切片项被复制到的共享内存位置。
所有使用&cmd
创建的指针都指向同一个内存位置。
这意味着在range
完成后,指针指向的内存位置中剩下的唯一值是range
迭代中的最后一个值。
这就是你得到输出的原因
update
update
update
【讨论】:
【参考方案2】:这是因为在一种情况下,您将地址传递给 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)
已编辑
这是[]obj
的一个切片,它有一个指针类型的字段 *string
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)
Playground example
在上述情况下,您正在创建一个字符串切片。
// []*string
func loop1()
slice := make([]obj, 0, 0)
for _, cmd := range cmdsP
slice = append(slice, objcmd)
for _, o := range slice
fmt.Println(*o.s)
fmt.Printf("%#v\n", slice)
而在第二种情况下,您正在创建 obj
结构的切片,其中包含指向 string
的指针字段。他们都是不同的情况。使用fmt
包查看您在loop1
函数中创建的切片的实际类型
Playground example
【讨论】:
感谢您的回答!你说So whenever you append an struct field to a slice
但如果我附加字符串字段slice := make([]string, 0, 0)
一切都很好。有什么区别? play.golang.org/p/7UdLlP2GiLw
@Rudziankoŭ 请检查编辑后的答案以上是关于切片指针和循环[重复]的主要内容,如果未能解决你的问题,请参考以下文章