【问题标题】:Set pointer to nil via function通过函数将指针设置为 nil
【发布时间】:2018-08-06 11:04:33
【问题描述】:

有一个函数可以设置一个指向nil值的指针:

func nilSetter(x *int) {
    x = nil
}

我有这样的sn-p代码:

i := 42
fmt.Println(&i)
nilSetter(&i)
fmt.Println(&i)

哪些打印:

0xc42008a000
0xc42008a000

虽然我期待:

0xc42008a000
nil

我知道这是因为函数 nilSetter 只是复制地址并将该副本设置为 nil。

但是我怎样才能正确地做到这一点?

【问题讨论】:

    标签: pointers go null


    【解决方案1】:

    实现这一点的唯一方法是使用指向指针的指针。而且它很笨重,所以可能不是你想要的:

    func nilSetter(x **int) {
        *x = nil
    }
    
    func main() {
        x := 2
        xp := &x
    
        fmt.Println(xp)
        nilSetter(&xp)
        fmt.Println(xp)
    
    }
    
    // Output:
    // 0x10414020
    // <nil>
    

    【讨论】:

    • 你应该fmt.Println(&amp;x) 而不是fmt.Println(&amp;xp)
    • @KenenbekArzymatov 请参阅@maksadbek 的答案。在 Go 中更改 &amp;x 的值是不可能的。
    【解决方案2】:

    这种行为的原因是因为Go中没有引用传递。

    两个变量的内容可以指向同一个存储位置。但是,不可能让它们共享相同的存储位置。 示例:

    package main
    
    import "fmt"
    
    func main() {
            var a int
            var b, c = &a, &a
            fmt.Println(b, c)   // 0x1040a124 0x1040a124
            fmt.Println(&b, &c) // 0x1040c108 0x1040c110
    }
    

    从您的代码中,nilSetter 的参数 x 指向某个位置,但它有自己的地址,当您为其设置 nil 时,您更改的是它的地址而不是它的地址正在指向。

    package main
    
    import "fmt"
    
    func nilSetter(x *int) {
        x = nil
        fmt.Println(x, &x) // <nil> 0x1040c140
    }
    
    func main() {
        i := 42
        fmt.Println(&i) // 0x10414020
        nilSetter(&i)
        fmt.Println(&i) // 0x10414020
    }
    

    这就是为什么指针总是有一个确切的地址,即使它的值是nil

    参考 Dave Cheney 的博客文章:https://dave.cheney.net/2017/04/29/there-is-no-pass-by-reference-in-go

    【讨论】:

      【解决方案3】:

      只需使用返回值并赋值即可。

      func nilSetter(x *int) *int {
          x = nil
          return x
      }
      
      x = nilSetter(x)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-06-16
        • 1970-01-01
        • 1970-01-01
        • 2013-10-31
        • 2018-01-05
        • 1970-01-01
        • 2017-11-05
        • 2017-05-29
        相关资源
        最近更新 更多