指向结构体的指针(或缺乏指针)

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

Pointer to a struct (or lack thereof)

问题

假设我定义了这个结构体:

type Vertex struct {
    X, Y float64
}

现在,在Go语言中,可以这样使用它:

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())
}

但是也可以不使用指针:

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

两种情况下的结果是相同的,但是它们在内部上有什么不同呢?使用指针会使程序运行更快吗?

PS. 我明白Abs()函数需要一个指针作为接收器。这解释了为什么在main函数中后面使用了指针。但是为什么当我不使用指针直接在结构体实例上调用Abs()时,程序不会报错呢?

英文:

Let's say I have defined this struct:

type Vertex struct {
	X, Y float64
}

now it's perfectly legal Go to use it like this:

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())
}

but it's also ok not to use a pointer:

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

The results in both cases is the same, but how are they different, internally? Does the use of pointer makes the program run faster?

PS. I get it that the Abs() function needs a pointer as a receiver. That explains the reason why a pointer has been used later in the main function. But why doesn't the program spit out an error when I don't use a pointer and directly call Abs() on a struct instance?

答案1

得分: 3

为什么在我不使用指针直接在结构体实例上调用Abs()时,程序没有报错?

因为你可以获取结构体实例的指针(地址)。

正如在《Golang中的指针接收器和值接收器是什么意思?》中所提到的:

Go会自动对指针进行取址和自动解引用(在大多数情况下),所以m := MyStruct{}; m.DoOtherStuff()仍然可以工作,因为Go会自动为你执行(&m).DoOtherStuff()

正如《在Golang中不要被指针和非指针方法接收器搞混》或《Go 101: 指针方法和值方法》所示,使用指针接收器(v *Vertex)可以避免拷贝,因为Go通过值传递一切

规范中提到的(方法值)

方法调用一样,使用指针接收器的非接口方法的引用将自动获取该值的地址:t.Mp等同于(&t).Mp

英文:

> why doesn't the program spit out an error when I don't use a pointer and directly call Abs() on a struct instance?

Because you can get the pointer to (address of) a struct instance.

As mentioned in "What do the terms pointer receiver and value receiver mean in Golang?"

> Go will auto address and auto-dereference pointers (in most cases) so m := MyStruct{}; m.DoOtherStuff() still works since Go automatically does (&m).DoOtherStuff() for you.

As illustrated by "Don't Get Bitten by Pointer vs Non-Pointer Method Receivers in Golang" or "Go 101: Methods on Pointers vs. Values", using a pointer receiver (v *Vertex) is great to avoid copy, since Go passes everything by value.

The spec mentions (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.

huangapple
  • 本文由 发表于 2015年2月1日 07:42:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/28257842.html
匿名

发表评论

匿名网友

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

确定