duanfen7676 2017-07-24 19:38
浏览 38
已采纳

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

This is pointers to pointers

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

}

When would you actually use this? You can properly come up with something where it would be easier to do something else, but that is not what I asking about. I really want to know where in production you would use this?

  • 写回答

3条回答 默认 最新

  • douzhixun8393 2017-07-25 07:46
    关注

    The goal to pass a pointer to something is if there is need to modify the pointed value. (We also use pointers to avoid copying large data structures when passing, but that is just for optimization.)

    Like in this example:

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

    Output is the expected (try it on the Go Playground):

    0
    1
    

    If parameter of inc() would receive an int only, it could only modify the copy and not the original value, and so the caller would not observe the changed value.

    Same goes with pointer to pointer to something. We use pointer to pointer to something, if we need to modify the pointed value, that is the pointed pointer. Like in this example:

    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
    }
    

    Output (try it on the Go Playground):

    <nil>
    0x1040a130 1
    <nil>
    

    The reason why pointer to pointer is not really used is because modifying a pointed value can be substituted by returning the value, and assigning it at the caller:

    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!
    }
    

    Output is the same (address might be different) (try it on the Go Playground):

    <nil>
    0x1040a130 1
    <nil>
    

    This variant is easier to read and maintain, so this is clearly the favored and wide-spread alternative to functions having to modify a pointer value.

    In languages where functions and methods can only have 1 return value, it usually requires additional "work" if the function also wants to return other values besides the pointer, e.g. a wrapper is to be created to accommodate the multiple return values. But since Go supports multiple return values, need for pointer to pointer basically drops to zero as it can be substituted with returning the pointer that would be set to the pointed pointer; and it does not require additional work and does not make code less readable.

    This is a very similar case to the builtin append() function: it appends values to a slice. And since the slice value changes (its length increases, also the pointer in it may also change if a new backing array needs to be allocated), append() returns the new slice value which you need to assign (if you want to keep the new slice).

    See this related question where a pointer to pointer is proposed (but also returning a pointer is also viable / preferred): Golang: Can the pointer in a struct pointer method be reassigned to another instance?

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 2024-五一综合模拟赛
  • ¥15 下图接收小电路,谁知道原理
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度
  • ¥30 关于#r语言#的问题:如何对R语言中mfgarch包中构建的garch-midas模型进行样本内长期波动率预测和样本外长期波动率预测
  • ¥15 ETLCloud 处理json多层级问题
  • ¥15 matlab中使用gurobi时报错
  • ¥15 这个主板怎么能扩出一两个sata口
  • ¥15 不是,这到底错哪儿了😭