Open atc0005 opened 4 years ago
From https://www.digitalocean.com/community/tutorials/defining-methods-in-go:
package main
import "fmt"
type Boat struct {
Name string
occupants []string
}
func (b *Boat) AddOccupant(name string) *Boat {
b.occupants = append(b.occupants, name)
return b
}
func (b Boat) Manifest() {
fmt.Println("The", b.Name, "has the following occupants:")
for _, n := range b.occupants {
fmt.Println("\t", n)
}
}
func main() {
b := &Boat{
Name: "S.S. DigitalOcean",
}
b.AddOccupant("Sammy the Shark")
b.AddOccupant("Larry the Lobster")
b.Manifest()
}
Snippet from description:
Within main, we define a new variable,
b
, which will hold a pointer to aBoat
(*Boat)
. We invoke theAddOccupant
method twice on this instance to add two passengers. TheManifest
method is defined on theBoat
value, because in its definition, the receiver is specified as(b Boat)
. In main, we are still able to callManifest
because Go is able to automatically dereference the pointer to obtain theBoat
value.b.Manifest()
here is equivalent to(*b).Manifest()
.
Worth stressing:
Boat
value.b.Manifest()
here is equivalent to (*b).Manifest()
From The Go Programming Language
:
The
(*Point).ScaleBy
method can be called by providing a*Point receiver
, like this:r := &Point{1, 2} r.ScaleBy(2) fmt.Println(*r) // "{2, 4}"
or this:
p := Point{1, 2} pptr := &p pptr.ScaleBy(2) fmt.Println(p) // "{2, 4}"
or this:
p := Point{1, 2} (&p).ScaleBy(2) fmt.Println(p) // "{2, 4}"
But the last two cases are ungainly. Fortunately, the language helps us here. If the receiver
p
is a variable of typePoint
but the method requires a*Point
receiver, we can use this shorthand:p.ScaleBy(2)
and the compiler will perform an implicit
&p
on the variable. This works only for variables, including struct fields likep.X
and array or slice elements likeperim[0]
.
A little further down:
But we can call a
Point
method likePoint.Distance
with a*Point receiver
, because there is a way to obtain the value from the address: just load the value pointed to by the receiver. *The compiler inserts an implicit `` operation for us.** These two function calls are equivalent:
pptr.Distance(q)
(*pptr).Distance(q)
and further:
Or the receiver argument has type
*T
and the receiver parameter has typeT
. The compiler implicitly dereferences the receiver, in other words, loads the value:pptr.Distance(q) // implicit (*pptr)
I obviously need to spend more time with this book (very detailed).
From Get Programming with Go:
type person struct { name, superpower string age int } timmy := &person{ name: "Timothy", age: 10, }
Furthermore, it isn’t necessary to dereference structures to access their fields. The following listing is preferable to writing
(*timmy).superpower
.timmy.superpower = "flying" fmt.Printf("%+v\n", timmy)
What’s the difference between
timmy.superpower
and(*timmy).superpower
?There’s no functional difference because Go automatically dereferences pointers for fields, but
timmy.superpower
is easier to read and is therefore preferable.
This is the example code from the https://www.udemy.com/course/go-the-complete-developers-guide/ course:
Here it looks like they're explicitly dereferencing the pointer receiver in order to get at the
firstName
field. I vaguely recall reading about Go automatically dereferencing for you with pointer receivers, so for the programmer's perspective this would be functionally equivalent (though less explicit perhaps?):Need to do some additional research to confirm that my memory is correct and if possible, figure out what the best practice is for this.