调用一个带有指针接收器的方法时,使用对象而不是指向它的指针?

huangapple go评论113阅读模式
英文:

Calling a method with a pointer receiver by an object instead of a pointer to it?

问题

vVertex的一个对象,Scale是指向Vertex的指针的方法。那么为什么v.Scale(10)不是错误的,考虑到v不是指向Vertex对象的指针?谢谢。

package main

import (
	"fmt"
	"math"
)

type Vertex struct {
	X, Y float64
}

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

func (v *Vertex) Scale(f float64) {
	v.X = v.X * f
	v.Y = v.Y * f
}

func main() {
	v := Vertex{3, 4}
	v.Scale(10)
	fmt.Println(v.Abs())
}
英文:

v is an object of Vertex, and Scale is a method for a pointer to Vertex. Then why is v.Scale(10) not wrong, given that v isn't a pointer to a Vertex object? Thanks.

package main

import (
	"fmt"
	"math"
)

type Vertex struct {
	X, Y float64
}

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

func (v *Vertex) Scale(f float64) {
	v.X = v.X * f
	v.Y = v.Y * f
}

func main() {
	v := Vertex{3, 4}
	v.Scale(10)
	fmt.Println(v.Abs())
}

答案1

得分: 11

[规范:调用:]

如果方法集(类型的)x 包含 m,并且参数列表可以赋值给 m 的参数列表,那么方法调用 x.m() 是有效的。如果 x可寻址的,并且 &x 的方法集包含 mx.m() 就是 (&x).m() 的简写

编译器看到 Scale() 有一个指针接收器,并且 v 是可寻址的(因为它是一个局部变量),所以 v.Scale(10) 将被解释为 (&v).Scale(10)

这只是规范提供的许多便利之一,以使源代码保持简洁。

英文:

Spec: Calls:

> A method call x.m() is valid if the method set of (the type of) x contains m and the argument list can be assigned to the parameter list of m. If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m().

The compiler sees that Scale() has a pointer receiver and also that v is addressable (as it is a local variable), so v.Scale(10) will be interpreted as (&v).Scale(10).

This is just one of the many conveniences the spec offers you so the source code can remain clean.

答案2

得分: 4

这是Go语言的自动解引用:

从https://golang.org/ref/spec#Method_values:

与选择器一样,使用指针引用值接收器的非接口方法将自动解引用该指针:pt.Mv 等同于 (*pt).Mv。

英文:

It's the Go automatic dereferencing:

From https://golang.org/ref/spec#Method_values:

>As with selectors, a reference to a non-interface method with a value receiver using a pointer will automatically dereference that pointer: pt.Mv is equivalent to (*pt).Mv.

huangapple
  • 本文由 发表于 2016年7月20日 20:32:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/38481420.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定