将指针传递给某物的目的是是否 需要 修改指向的值。(我们也使用指针来避免在传递时复制大型数据结构,但这只是为了优化。)
像这个例子一样:
func main() { var i int fmt.Println(i) inc(&i) fmt.Println(i)}func inc(i *int) { *i++}预期的输出(在Go Playground上尝试):
01
如果of的参数仅
inc()接收
int,则只能修改副本,而不能修改原始值,因此调用者将不会观察到更改后的值。
指向某物的指针也是如此。如果需要修改指向的值,则使用指向某个对象的指针,即指向的指针。像这个例子一样:
func main() { var i *int fmt.Println(i) alloc(&i, 1) fmt.Println(i, *i) setTonil(&i) fmt.Println(i)}func alloc(i **int, initial int) { *i = new(int) **i = initial}func setTonil(i **int) { *i = nil}输出(在Go Playground上尝试):
<nil>0x1040a130 1<nil>
之所以没有真正使用指向指针的原因,是因为可以通过返回值并将其分配给调用方来代替修改指向的值:
func main() { var i *int fmt.Println(i) i = alloc(1) fmt.Println(i, *i) i = setTonil() fmt.Println(i)}func alloc(initial int) *int { i := new(int) *i = initial return i}func setTonil() *int { return nil // Nothing to do here, assignment happens at the caller!}输出是相同的(地址可能不同)(在Go Playground上尝试):
<nil>0x1040a130 1<nil>
此变体更易于阅读和维护,因此,这显然是必须修改指针值的函数的广泛青睐的替代方案。
在函数和方法只能有一个返回值的语言中,如果函数还希望返回除指针之外的其他值,则通常需要附加的“工作”,例如,将创建一个包装器来容纳多个返回值。但是由于Go支持多个返回值,因此指针指针的需求基本上降为零,因为可以用返回设置为指向指针的指针代替它。并且不需要额外的工作,也不会使代码的可读性降低。
这与内置
append()函数非常相似:将值附加到切片。而且由于切片值发生变化(其长度增加,如果需要分配新的后备数组,其中的指针也可能会更改),因此
append()返回您需要分配的新切片值(如果要保留新切片)
。



