Golang Go语言中 A Tour of Go-Pointer receivers 一点疑问
Golang Go语言中 A Tour of Go-Pointer receivers 一点疑问
https://tour.golang.org/methods/4
刚开始学 go,从 A Tour of Go 开始看的,求大佬帮忙看看,非常感谢
package main
import (
“fmt”
“math”
)
type Vertex struct {
X, Y float64
}
func (v Vertex) Abs() float64 {
return math.Sqrt(v.Xv.X + v.Yv.Y)
}
func (v *Vertex) Scale(f float64) { //这里 receiver 的类型是 指针类型
v.X = v.X * f
v.Y = v.Y * f
}
func main() {
v := Vertex{3, 4}
v.Scale(10) //但是 v 是 Vertex 类型啊?为什么也能运行通过?
fmt.Println(v.Abs())
}
package main
import (
"fmt"
"math"
)
type Vertex struct {
X, Y float64
}
func (v Vertex) Abs() float64 {
return math.Sqrt(v.Xv.X + v.Yv.Y)
}
func (v *Vertex) Scale(f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
func main() {
v := Vertex{3, 4}
var m *Vertex
m = &v //我理解的应该是这样的
m.Scale(10)
fmt.Println(v.Abs())
}
更多关于Golang Go语言中 A Tour of Go-Pointer receivers 一点疑问的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
编译器自动帮你做了你想到的步骤
更多关于Golang Go语言中 A Tour of Go-Pointer receivers 一点疑问的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
为了写代码方便。否则第一个例子你得这么写(&v).Scale(10),go 默认帮你加上了取地址符,前提是变量本身是可以取地址的。
如果你写了一个签名为 func GetVertex() Vertex 的函数,GetVertex().Scale(10)就会失败,因为返回的临时变量不可取地址。
https://golang.org/ref/spec#Method_values
As with method calls, a reference to a non-interface method with a pointer receiver using an addressable value will automatically take the address of that value: t.Mp is equivalent to (&t).Mp.go<br>f := <a target="_blank" href="http://t.Mv" rel="nofollow noopener">t.Mv</a>; f(7) // like <a target="_blank" href="http://t.Mv" rel="nofollow noopener">t.Mv</a>(7)<br>f := <a target="_blank" href="http://pt.Mp" rel="nofollow noopener">pt.Mp</a>; f(7) // like <a target="_blank" href="http://pt.Mp" rel="nofollow noopener">pt.Mp</a>(7)<br>f := <a target="_blank" href="http://pt.Mv" rel="nofollow noopener">pt.Mv</a>; f(7) // like (*pt).Mv(7)<br>f := <a target="_blank" href="http://t.Mp" rel="nofollow noopener">t.Mp</a>; f(7) // like (&t).Mp(7)<br>f := makeT().Mp // invalid: result of makeT() is not addressable<br>
Although the examples above use non-interface types, it is also legal to create a method value from a value of interface type.go<br>var i interface { M(int) } = myVal<br>f := i.M; f(7) // like i.M(7)<br>
反过来就不行
package main
import (
“fmt”
“math”
)
type Vertex struct {
X, Y float64
}
func Abs(v Vertex) float64 {
return math.Sqrt(v.Xv.X + v.Yv.Y)
}
func Scale(v Vertex, f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
func main() {
v := Vertex{3, 4}
Scale(&v, 10)
fmt.Println(Abs(v))
}
cannot use &v (type *Vertex) as type Vertex in argument to Scale
编译器自己加了。。。
你的例子错了,这个报错是说参数类型不匹配。
是,评论那个是函数(参数类型不对),不是方法(接收者类型),我搞混淆了
反过来也是可以的
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 main() {
v := Vertex{3, 4}
fmt.Println((&v).Abs())
}
因为编译器给指针类型*Vertex 隐式声明了一个同名方法。https://gfw.go101.org/article/method.html#implicit-pointer-methods
关于你在《A Tour of Go》中提到的关于Pointer receivers(指针接收器)的疑问,我很乐意为你提供一些解答。
在Go语言中,方法接收器可以是值接收器也可以是指针接收器。选择哪种接收器取决于具体的需求。
当你需要修改接收器指向的对象时,应该使用指针接收器。因为值接收器在方法调用时会进行值拷贝,方法内对接收器的修改不会影响到原始数据。而指针接收器则直接传递对象的地址,方法内对接收器的修改会反映到原始数据上。
此外,如果接收器是一个较大的结构体,使用值接收器会导致性能下降,因为每次方法调用都会进行大量的数据拷贝。而指针接收器则避免了这个问题,因为它只是传递了对象的地址。
在编写代码时,应该根据实际需求选择合适的接收器类型。如果不需要修改接收器指向的对象,且接收器较小,那么值接收器是一个不错的选择。否则,应该使用指针接收器。
最后,需要注意的是,即使你不需要修改接收器指向的对象,但在某些情况下(如实现接口时),仍然可能需要使用指针接收器。这是因为一些接口规定了必须使用指针接收器的方法。
希望这些解答能够帮助你更好地理解Go语言中的Pointer receivers。如果你还有其他问题,欢迎随时提问。