英文:
Are pointers dereferenced by default inside of methods?
问题
我对Go语言中的结构体方法感到困惑。我在一个教程中跟着做,他们写了以下代码:
func (p *Page) save() error {
filename := p.Title + ".txt"
return ioutil.WriteFile(filename, p.Body, 0600)
}
根据我的理解,p
是一个指针,如果要获取属性的话,需要对指针进行解引用,例如:
filename := (*p).Title + ".txt"
这只有在点号(.
)的作用类似于C++中的->
时才有意义。我错过了什么吗?
英文:
I'm confused by methods on structs in Go. I've following along in a tutorial in which they have:
func (p *Page) save() error {
filename := p.Title + ".txt"
return ioutil.WriteFile(filename, p.Body, 0600)
}
From my understanding, p
is pointer and you would need to dereference the pointer before retrieving a property for example:
filename := (*p).Title + ".txt"
The only way this makes sense to me is if the dot is acting like ->
in C++. What am I missing?
答案1
得分: 31
是的,对结构体的指针进行选择操作时,指针会自动解引用。根据选择器规范的说明:
> 以下规则适用于选择器:
> 1. 对于类型为 T
或 *T
的值 x
,其中 T
不是指针类型或接口类型,x.f
表示在 T
中最浅层的字段或方法,只要存在这样的 f
。如果最浅层的深度上不止一个 f
,则选择器表达式是非法的。
>
> ...
>
> 3. 作为一个例外,如果 x
的类型是一个命名的指针类型,并且 (*x).f
是一个有效的选择器表达式,表示一个字段(但不是方法),那么 x.f
是 (*x).f
的简写形式。
因此,以下两个语句是相同的(第一个语句更常用):
filename := p.Title + ".txt"
filename := (*p).Title + ".txt"
英文:
Yes, the pointer to the struct is automatically dereferenced. From the spec on selectors:
> The following rules apply to selectors:
> 1. For a value x
of type T
or *T
where T
is not a pointer or interface type, x.f
denotes the field or method at the shallowest depth in T
> where there is such an f
. If there is not exactly one f
with
> shallowest depth, the selector expression is illegal.
>
> ...
>
> 3. As an exception, 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
.
Therefore, the following two statements are the same (with the first being preferred):
filename := p.Title + ".txt"
filename := (*p).Title + ".txt"
答案2
得分: 2
在Go语言中,访问结构体的字段时不需要使用指针引用或特殊的访问操作符。
myRef := &ILikeCompositeLiteralInitilization{}
fmt.Println(myRef.Dereferenced)
与下面的代码功能上是等价的:
fmt.Println((*myRef).Dereferenced)
值得注意的是,对于函数的行为不同。也就是说,如果要调用一个接收值而不是指针的方法,我必须进行解引用。
func (*ILikeCompositeLiteralInitilization) PointerVersion()
func (ILikeCompositeLiteralInitilization) ValueVersion()
myRef.PointerVersion() // 编译器可以接受
myRef.ValueVersion() // 无法编译
(*myRef).ValueVersion() // 编译器可以接受
基本上,对于函数来说,不会发生隐式的解引用或取地址操作,因此你的代码无法编译通过。
英文:
You do not have to deference pointers or use a special access operator to access the fields of a struct in Go.
myRef := &ILikeCompositeLiteralInitilization{}
fmt.Println(myRef.Dereferenced);
is functionally equivalent to;
fmt.Printn((*myRef).Dereferenced);
Possibly worth noting that the behavior for functions is not like this. Meaning, I would have to dereference to invoke a method who's recieving type is the value and not a pointer. IE;
func (*ILikeCompositeLiteralInitilization) PointerVersion()
func (ILikeCompositeLiteralInitilization) ValueVersion()
myRef.PointerVersion() // compiler likes this
myRef.ValueVersion() // won't compile
(*myRef).ValueVersion() // compiler is OK with this
Basically, with functions no implicit dereference or address of type operation will occur, your code won't compile.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论