这是指向指针的指针
package main import "fmt" func main() { var num int fmt.Println(&num) // 0x...0 makePointer(&num) } func makePointer(firstPointer *int) { fmt.Println(firstPointer) // 0x...0 fmt.Println(&firstPointer) // 0x...1 makePointerToAPointer(&firstPointer) } func makePointerToAPointer(secondPointer **int) { fmt.Println(secondPointer) // 0x...1 fmt.Println(&secondPointer) // 0x...2 }
您何时真正使用此功能?您可以适当地提出一些可以更轻松地执行其他操作的方法,但这不是我要的。我真的想知道您将在生产中使用此功能吗?
将指针传递给某物的目的是是否 需要 修改指向的值。(我们也使用指针来避免在传递时复制大型数据结构,但这只是为了优化。)
像这个例子一样:
func main() { var i int fmt.Println(i) inc(&i) fmt.Println(i) } func inc(i *int) { *i++ }
预期的输出(在Go Playground上尝试):
0 1
如果of的参数仅inc()接收int,则只能修改副本,而不能修改原始值,因此调用者将不会观察到更改后的值。
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上尝试):
此变体更易于阅读和维护,因此,这显然是必须修改指针值的函数的广泛青睐的替代方案。
在函数和方法只能有一个返回值的语言中,如果函数还希望返回除指针之外的其他值,则通常需要附加的“工作”,例如,将创建一个包装器来容纳多个返回值。但是由于Go支持多个返回值,因此指针指针的需求基本上降为零,因为可以用返回设置为指向指针的指针代替它。并且不需要额外的工作,也不会使代码的可读性降低。
这与内置append()函数非常相似:将值附加到切片。而且由于切片值发生变化(其长度增加,如果需要分配新的后备数组,其中的指针也可能会更改),因此append()返回您需要分配的新切片值(如果要保留新切片) 。
append()