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?
Yes, the pointer to the struct is automatically dereferenced. From the spec on selectors:
The following rules apply to selectors:
- For a value
x
of typeT
or*T
whereT
is not a pointer or interface type,x.f
denotes the field or method at the shallowest depth inT
where there is such anf
. If there is not exactly onef
with shallowest depth, the selector expression is illegal....
- 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"
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.