Where does Go define that p.Field (as opposed to (*p).Field) is a valid syntax even when p is a pointer to a struct?

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

Where does Go define that p.Field (as opposed to (*p).Field) is a valid syntax even when p is a pointer to a struct?

问题

这是我的Go程序。

package main

import (
	"fmt"
)

type Person struct {
	Name string
}

func main() {
	p := &Person{"Jack"}

	// 下面的语句是有意义的。我们解引用指针以访问Person对象,然后获取其Name字段。
	fmt.Println((*p).Name)

	// 但是下面的语句是没有意义的。在不解引用指针的情况下,如何直接从指针中检索Name字段?
	fmt.Println(p.Name)
}

以下是输出结果。

$ go run foo.go 
Jack
Jack

p的类型为*Person,即指向Person的指针时,如何在不解引用的情况下访问其字段Name是合法的?我看到所有的Go教程都使用syntax p.Name而不是(*p).Name,但是Go语言在哪里定义了p.Person作为合法的语法?

英文:

Here is my Go program.

package main

import (
	"fmt"
)

type Person struct {
	Name string
}

func main() {
	p := &Person{"Jack"}

	// The following statement makes sense. We dereference the
	// pointer to reach the Person object and then retrieve its Name
	// field.
	fmt.Println((*p).Name)

	// But the following statement does not make sense. How does
	// this code work by retrieving the Name field directly from the
	// pointer without dereferencing it?
	fmt.Println(p.Name)
}

Here is the output.

$ go run foo.go 
Jack
Jack

When p is of type *Person, i.e. a pointer to Person, how is it legal to access its field Name without dereferencing it? I see all Go tutorials using the syntax p.Name instead of (*p).Name but where exactly the Go language defines p.Person as a legal syntax?

答案1

得分: 3

规范:选择器:

> 以下规则适用于选择器:
>
> [...] 如果 x 的类型是一个命名指针类型,并且 (*x).f 是一个有效的选择器表达式,表示一个字段(但不是一个方法),x.f(*x).f 的简写

语言规范中的指针语法可以让你感觉在某些情况下甚至没有使用指针。解引用指针以访问其字段就是其中之一。此外,如果可寻址,你可以在非指针值上调用具有指针接收器的方法,参见https://stackoverflow.com/questions/38481420/calling-a-method-with-a-pointer-receiver-by-an-object-instead-of-a-pointer-to-it/38481697#38481697

此外,你可以对数组指针进行索引和切片操作,例如,如果 a 是指向数组类型的指针:

  • a[x](*a)[x] 的简写

  • a[low : high](*a)[low : high] 的简写。

英文:

Spec: Selectors:

> The following rules apply to selectors:
>
> [...] if the type of x is a named pointer type and (*x).f is a valid selector expression denoting a field (but not a method), x.f is shorthand for (*x).f.

The language spec helps you with the pointer syntax to make it feel you're not even using pointers in some cases. Dereferencing a pointer to access its field is one of them. Also you can call methods that have pointer receiver on non-pointer values if they are addressable, see https://stackoverflow.com/questions/38481420/calling-a-method-with-a-pointer-receiver-by-an-object-instead-of-a-pointer-to-it/38481697#38481697

Also you can index and slice array pointers, e.g. if a is a pointer to array type:

  • a[x] is shorthand for (*a)[x]

  • and a[low : high] is shorthand for (*a)[low : high].

huangapple
  • 本文由 发表于 2017年5月2日 12:01:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/43729893.html
匿名

发表评论

匿名网友

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

确定