切片指针和循环

Rud*_*koŭ 2 pointers loops go slice

我认为这个问题被问了好几次,但我仍然感到困惑:

我有以下代码:

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
}
Run Code Online (Sandbox Code Playgroud)

https://play.golang.org/p/65Le_8Pi3Mi

唯一的区别在于切片语义[]*string[]string它如何改变cmd变量的行为?您能否详细绘制或解释在通过两个循环进行迭代期间内存中会发生什么?

Zak*_*Zak 7

当你调用range一个集合时,go 运行时会初始化 2 个内存位置;一个用于索引(在本例中为_),一个用于值cmd

然后 range 的作用是获取集合中的每个项目并将它们复制到它在您调用时创建的内存位置range

这意味着切片中的每个项目都被一个一个地放入该内存位置。

当你这样做时,&cmd你正在接受一个指针。该指针指向每个切片项目被复制到的共享内存位置。

使用&cmdall创建的所有指针都指向相同的内存位置。

这意味着在range完成之后,您的指针指向的内存位置中剩下的唯一值是range迭代中的最后一个值。

这就是为什么你得到输出

update
update
update
Run Code Online (Sandbox Code Playgroud)