Golang指针

mer*_*ard 21 pointers go

我目前正在学习用Go语言编程.我在理解Go指针方面遇到了一些困难(现在我的C/C++还很远......).例如,在Tour of Go#52(http://tour.golang.org/#52)中,我读到:

type Vertex struct {
    X, Y float64
}

func (v *Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func main() {
    v := &Vertex{3, 4}
    fmt.Println(v.Abs())
}
Run Code Online (Sandbox Code Playgroud)

但如果不是

func (v *Vertex) Abs() float64 {
[...]
v := &Vertex{3, 4}
Run Code Online (Sandbox Code Playgroud)

我写:

func (v Vertex) Abs() float64 {
[...]
v := Vertex{3, 4}
Run Code Online (Sandbox Code Playgroud)

甚至:

func (v Vertex) Abs() float64 {
[...]
v := &Vertex{3, 4}
Run Code Online (Sandbox Code Playgroud)

反之亦然:

func (v *Vertex) Abs() float64 {
[...]
v := Vertex{3, 4}
Run Code Online (Sandbox Code Playgroud)

我得到了完全相同的结果.是否存在差异(记忆方面等)?

小智 33

您的示例使用了两种不同的Go语言规则:

  1. 可以从具有值接收器的方法导出具有指针接收器的方法.这样func (v Vertex) Abs() float64会自动生成一个额外的方法实现:

    func (v Vertex) Abs() float64 { return math.Sqrt(v.X*v.X+v.Y*v.Y) }
    func (v *Vertex) Abs() float64 { return Vertex.Abs(*v) }  // GENERATED METHOD
    
    Run Code Online (Sandbox Code Playgroud)

    编译器将自动找到生成的方法:

    v := &Vertex{3, 4}
    v.Abs()  // calls the generated method
    
    Run Code Online (Sandbox Code Playgroud)
  2. Go可以自动获取变量的地址.在以下示例中:

    func (v *Vertex) Abs() float64 { return math.Sqrt(v.X*v.X+v.Y*v.Y) }
    func main() {
        v := Vertex{3, 4}
        v.Abs()
    }
    
    Run Code Online (Sandbox Code Playgroud)

    表达式v.Abs()等效于以下代码:

    vp := &v
    vp.Abs()
    
    Run Code Online (Sandbox Code Playgroud)

  • 在输入`func(v Vertex)Abs()`之前,会创建一个新的struct Vertex副本. (2认同)

zzz*_*zzz 13

有区别.例如,非指针接收器形式强制该方法在副本上工作.这样,该方法无法改变它所调用的实例 - 它只能访问该副本.在时间/内存性能/消耗等方面可能无效.

OTOH,指向具有指针接收器的实例和方法的指针允许在需要时容易地实例共享(和变异).

更多细节在这里.