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条)

报告相同问题?

悬赏问题

  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘
  • ¥15 perl MISA分析p3_in脚本出错
  • ¥15 k8s部署jupyterlab,jupyterlab保存不了文件
  • ¥15 ubuntu虚拟机打包apk错误
  • ¥199 rust编程架构设计的方案 有偿
  • ¥15 回答4f系统的像差计算
  • ¥15 java如何提取出pdf里的文字?