我写了一些奇怪的代码,但我不确定它为什么会起作用以及我可以从中学到什么。我有一个来自另一个结构的切片类型构建。我在切片类型上创建了一个函数来修改它自己。要做到这一点,我似乎不得不抛弃一点点。
我正在尝试学习Go中的指针并希望得到一些帮助。这是一个例子(http://play.golang.org/p/roU3MEeT3q):
var ClientNames = []string {"Client A", "Client B", "ClientC"}
type InvoiceSummaries []InvoiceSummary
type InvoiceSummary struct {
Client string
Amt int
}
func (summaries *InvoiceSummaries) BuildFromAbove() {
for _, name := range ClientNames {
*summaries = append(*summaries, InvoiceSummary{name, 100})
}
}
我的问题是:每个*的目的是什么?为什么我不使用任何&?
答案 0 :(得分:1)
你必须使用指针作为接收器 - (summaries *InvoiceSummaries)
- 因为否则参数是通过值传递的,有一个指针意味着你传递对该值的引用。如果不是那样的话,那么根本无法修改集合。
在方法体内部,您使用*
,因为它是dereferncing运算符并返回地址处的值。 &符号(&
)是相反的,它给出了值的地址。
答案 1 :(得分:1)
您的代码没有任何问题,但通常不会使用切片的地址。切片是一个小结构,gophers通常很乐意通过值传递。如果方法或函数正在创建新切片,则gopher很乐意再次按值返回新切片作为返回值。
当然,按值传递切片并不能保证在方法/函数返回时有关后备存储的任何内容保持不变。因此,它无法用作保证切片数据元素不变的方式。
答案 2 :(得分:1)
每个* *的目的是什么?
通过将方法接收器作为指针,您可以轻松更改对象的属性。我认为这是其中一个好处。下面的例子将证明这一点。
package main
import "fmt"
type someStruct struct {
someVar int
}
func (s someStruct) changeVal1(newVal int) {
s.someVar = newVal
}
func (s *someStruct) changeVal2(newVal int) {
s.someVar = newVal
}
func main() {
s := someStruct{0}
fmt.Println(s) // {0}
s.changeVal1(3)
fmt.Println(s) // {0}
s.changeVal2(4)
fmt.Println(s) // {4}
(&s).changeVal2(5)
fmt.Println(s) // {5}
}
为什么我没有使用任何&?
指针方法接收器很特殊,它也可以从非指针结构对象中调用。 s.changeVal2(4)
和(&s).changeVal2(5)
都是有效的&会影响someVar
的价值。