一尘不染

切片结构vs指向结构的指针

go

我不理解以下代码的行为。在创建作为结构指针切片的匹配结构列表时,代码始终会打印原始数组的最后一个元素(实际上不是匹配项),它会打印12和12。但是,如果将匹配项更改为[]窗口小部件代替[] * Widget,然后将输出10和11。

为什么是这样?

package main

import (
    "fmt"
)

func main() {

    type Widget struct {
        id    int
        attrs []string
    }

    widgets := []Widget{
        Widget{
            id:    10,
            attrs: []string{"blah", "foo"},
        },
        Widget{
            id:    11,
            attrs: []string{"foo", "bar"},
        },
        Widget{
            id:    12,
            attrs: []string{"xyz"},
        },
    }

    var matches []*Widget
    for _, w := range widgets {
        for _, a := range w.attrs {
            if a == "foo" {
                matches = append(matches, &w)
                break
            }
        }
    }

    for _, m := range matches {
        fmt.Println(m.id)
    }

}

阅读 172

收藏
2020-07-02

共1个答案

一尘不染

那是因为当您使用指针时,您将添加&w到数组。

请注意,w实际上这是循环中使用的局部变量,因此,这不是您要添加到matches数组中的地址。

(即使变量的 w在循环中发生变化,其 地址也 保持不变)

循环结束时,w以最后一个值结束,这就是为什么它打印12两次的原因。

您需要添加匹配的元素的地址。

如果您这样做:

matches = append(matches, &widgets[i])

然后它也可以很好地与指针一起工作。

修改后的Go游乐场供您测试:

https://play.golang.org/p/YE-cokyEHu

2020-07-02