2

为什么这两个destroy函数都不会将指针更改为 nil 以及如何创建这样的函数?

package main

import (
    "fmt"
)

type position struct {
    x int
    y int
}

func (p *position) destroy() {
    p = nil
}

func destroy(p *position) {
    p = nil
}

func main() {
    p1 := &position{1,1}
    p2 := &position{2,2}
    p1.destroy()
    destroy(p2)

    if p1 == nil {
        fmt.Println("p1 == nil")
    } else {
        fmt.Println(p1)
    }

    if p2 == nil {
        fmt.Println("p2 == nil")
    } else {
        fmt.Println(p2)
    }

}

输出:

&{1 1}
&{2 2}

https://play.golang.org/p/BmZjX1Hw24u

4

1 回答 1

4

您需要一个指向指针的指针来更改指针的值。

这是您的代码示例,已修改为执行此操作(操场):

package main

import (
    "fmt"
)

type position struct {
    x int
    y int
}

func destroy(p **position) {
    *p = nil
}

func main() {
    p1 := &position{1, 1}
    destroy(&p1)

    if p1 == nil {
        fmt.Println("p1 == nil")
    } else {
        fmt.Println(p1)
    }
}

在您当前的代码中

func destroy(p *position) {
    p = nil
}

内部destroy,p是一个保存position结构地址的值。通过给自己分配一些东西p,你只是让它持有一些其他position结构(或nil)的地址。您没有修改传入的原始指针。

这与试图通过赋值来修改其参数的函数没有什么不同:

// This will not actually modify the argument passed in by the caller
func setto2(value int) {
  value = 2
}

go 规范在关于调用和调用参数的部分中说:

在它们被评估之后,调用的参数按值传递给函数,被调用的函数开始执行。函数的返回参数在函数返回时按值传回调用函数。

于 2019-02-16T19:41:00.540 回答