Pointers 指向指针(例如**int)的指针有什么用例?

Pointers 指向指针(例如**int)的指针有什么用例?,pointers,go,Pointers,Go,这是指向指针的指针 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)

这是指向指针的指针

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

}

你什么时候会用这个?你可以适当地想出一些更容易做其他事情的方法,但这不是我要问的。我真的很想知道在生产中您将在何处使用此功能?

同样,指向某个值的指针可以让您对同一个值进行多次引用,以便在该值发生变化时获得该值的一致视图,当指针更改为指向内存中的不同位置时,指向指针的指针允许您对同一引用进行多个引用,以获得指针的一致视图


我不能说我曾经在Go中看到过我能想到的实际应用。

同样,指向值的指针可以让您对同一个值进行多次引用,以便在值发生变化时获得一致的值视图,当指针更改为指向内存中的不同位置时,指向指针的指针允许您对同一引用进行多个引用,以获得指针的一致视图


我不能说我曾经在Go的实践中看到过我能想到的它。

指向指针的指针有时在函数参数中是有意义的;可能不是
**int
,而是指向某个结构的指针,您希望函数能够更改变量指向的对象,而不仅仅是更改结构的内容。例如,Go编译器的内部有一些函数采用
**节点
(参见cmd/compile/internal/gc/racewack.Go)

我自己也编写了两个函数,它们采用
**html.Node
;它们在一个HTML页面上运行,该页面可能已经或可能还没有被解析为
*HTML.Node
s树,它们可能需要或可能不需要解析该页面,但如果需要,我希望保留解析后的树,这样我就不必再解析它了。这些文件位于github.com/andybalholm/redwood/prune.go


它们在没有多个返回值的语言中更为常见,因为它们可以作为一种返回附加值(即指针)的方式。许多Objective-C方法将
NSError**
作为其最后一个参数,因此它们可以选择返回
NSError*

指针,指向函数参数中有时有意义的指针;可能不是
**int
,而是指向某个结构的指针,您希望函数能够更改变量指向的对象,而不仅仅是更改结构的内容。例如,Go编译器的内部有一些函数采用
**节点
(参见cmd/compile/internal/gc/racewack.Go)

我自己也编写了两个函数,它们采用
**html.Node
;它们在一个HTML页面上运行,该页面可能已经或可能还没有被解析为
*HTML.Node
s树,它们可能需要或可能不需要解析该页面,但如果需要,我希望保留解析后的树,这样我就不必再解析它了。这些文件位于github.com/andybalholm/redwood/prune.go


它们在没有多个返回值的语言中更为常见,因为它们可以作为一种返回附加值(即指针)的方式。许多Objective-C方法将
NSError**
作为其最后一个参数,以便它们可以选择性地返回
NSError*

传递指向某个对象的指针的目标是,如果需要修改指向的值。(我们也使用指针来避免在传递时复制大型数据结构,但这只是为了优化。)

如本例所示:

func main() {
    var i int
    fmt.Println(i)
    inc(&i)
    fmt.Println(i)
}

func inc(i *int) {
    *i++
}
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
}
输出是预期的(请在上尝试):

如果
inc()
的参数只会收到一个
int
,它只能修改副本而不能修改原始值,因此调用者不会观察到更改后的值

指向某物的指针也是如此。我们使用指向某个对象的指针,如果我们需要修改指向的值,那就是指向的指针。如本例所示:

func main() {
    var i int
    fmt.Println(i)
    inc(&i)
    fmt.Println(i)
}

func inc(i *int) {
    *i++
}
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
}
输出(在上尝试):

输出相同(地址可能不同)(请在上尝试):


0x1040a130 1
这种变体更易于阅读和维护,因此这显然是需要修改指针值的函数的首选和广泛的替代方法

在函数和方法只能有1个返回值的语言中,如果函数还希望返回指针以外的其他值,则通常需要额外的“工作”,例如,要创建一个包装以容纳多个返回值。但由于Go支持多个返回值,指针对指针的需求基本上降为零,因为它可以用返回将被设置为指针的指针来代替;而且它不需要额外的工作,也不会降低代码的可读性

这与内置函数非常相似:它将值附加到切片。由于切片值发生变化(其长度增加,如果需要分配新的备份数组,其中的指针也可能发生变化),
append()
返回需要分配的新切片值(如果要保留新切片)


请参阅此相关问题,其中建议使用指向指针的指针(但返回指针也是可行的/首选的):

将指针传递给某个对象的目标是是否需要修改指针的值。(我们也使用指针来避免在传递时复制大型数据结构,但这只是为了优化。)

如本例所示:

func main() {
    var i int
    fmt.Println(i)
    inc(&i)
    fmt.Println(i)
}

func inc(i *int) {
    *i++
}
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
}
输出是预期的(请在上尝试):

如果
inc()
的参数只会收到一个
int
,它只能修改副本而不能修改原始值,因此调用者不会观察到更改后的值

指向某物的指针也是如此。我们使用指向某个对象的指针,如果我们需要修改指向的值,那就是指向的指针。锂