英文:
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]的简写。 
英文:
> 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]. 
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论