Golang how to range in pointer array

huangapple go评论79阅读模式
英文:

Golang how to range in pointer array

问题

如果我有一个PersonManager结构体,并且它有一个*[]Person数组。我想遍历这个数组中的每个项。例如:

manager := *PersonManager

for ii := 0; len(*manager.allPersons); ii++{
    fmt.Println(manager.allPersons[:ii].name)
}

对于这个例子,manager变量是一个指针,而该变量中的数组也是一个指针。我该如何遍历这些项?

注意:我得到了"cannot slice manager.allPersons (type *[]Person)"的错误提示。

英文:

if I have PersonManager struct and it has *[]Person array. I want to range every item in this array. For example

manager := *PersonManager

for ii := 0; len(*manager.allPersons); ii++{
    fmt.Println(manager.allPersons[:ii].name)
}

for this example, manager variable is pointer and array that in this variable is pointer too. How can I range this items?

Not: I m getting cannot slice manager.allPersons (type *[]Person) error

答案1

得分: 12

使用range关键字。https://github.com/golang/go/wiki/Range

for i, person := range *manager.allPerson {
    fmt.Println(person.name)
}

请注意,如果您不使用索引变量i,编译器会报错。如果您不打算使用它,请用_替换。

进一步解释一下,您最初的错误是因为您第一次正确地解引用了*[]Person,但在for循环内部没有解引用。

fmt.Println(manager.allPersons[:ii].name) // 错误
fmt.Println((*manager.allPersons)[:ii].name) // 正确

另外,由于您的slice包含Person结构体的,如果您在range表达式中使用可选的第二个值,它将不得不进行复制。因此,保持只使用索引会更高效。

作为建议,不要使用*[]Person,而是使用[]*Person,这可能是您本来打算使用的。slice已经是一个指针值。使用[]*Person,您不必担心range表达式会复制整个结构体,因为它只是指向Person的指针。

实际上,除非您将类型更改为[]*Person或索引到slice中,否则无法在range循环中反映出对slice的更改,因为结构体值将是一个副本。请参阅https://github.com/golang/go/wiki/Range#gotchas,但请注意,如果该值是指针值,则不会出现此问题。

英文:

Use the range keyword. https://github.com/golang/go/wiki/Range

for i, person := range *manager.allPerson {
    fmt.Println(person.name)
}

Note that the compiler will be angry if you don't use the index var i. If you don't intend to use it, replace with _.

To further explain, your original error was due to the fact that you correctly dereferenced your *[]Person the first time, but not inside the for loop.

fmt.Println(manager.allPersons[:ii].name) // wrong
fmt.Println((*manager.allPersons)[:ii].name) // right

Also, given that your slice contains Person struct values, it will have to copy it if you use the optional second value in the range expression. Thus, it would be more efficient to keep using just the indexes.

As a suggestion, don't use a *[]Person, use []*Person, which is probably what you intended to use anyway. A slice is already a pointer value. Using []*Person you don't have to fear a copy by the range expression because it is simply a pointer to a Person instead of the entire struct.

In fact, unless you either change the type to []*Person or index into the slice you won't be able to have changes reflected in the slice because a struct value will be a copy in the range loop. See https://github.com/golang/go/wiki/Range#gotchas but be aware that if the value is a pointer value, this isn't an issue.

答案2

得分: 2

我觉得你可能对指针有些混淆。你不需要在任何地方解引用指针。像这样的代码应该可以工作:

for i := 0; i < len(manager); i++ {
	fmt.Println(manager[i].Name)
}

在这里运行Go代码:
https://play.golang.org/p/P8wAp4wIGs

英文:

I think you might be mixed up by the pointers. You don't need to dereference your pointer anywhere. Something like this should work:

for i := 0; i &lt; len(manager); i++ {
	fmt.Println(manager[i].Name)
}

GoPlay here:
https://play.golang.org/p/P8wAp4wIGs

huangapple
  • 本文由 发表于 2017年5月12日 01:17:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/43921889.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定