You might know methods from other programming languages like Java. In most cases, methods are functions, that are part of a class.
- Go doesn’t have classes
- Methods can be defined on types
- A method has a special receiver argument
- Receiver: Between
func
and and method name - Still, methods are functions
func (v Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
In this case, Abs
method has receiver of type Vertex
named v
.
type Person struct {
Name string
Age int
}
func (p Person) GreetPerson() {
fmt.Println("Hello, my name is", p.Name)
}
func main() {
// defer fmt.Println("Hello, World!")
max := Person{"Max", 25}
max.GreetPerson()
}
Methods on non-struct types
In this case, not a struct but only a type:
type Person string
func (p Person) greetPerson() string {
return "Hello, " + string(p)
}
Only types within the same package can be used
Pointer receivers
- Methods
func (p Person) ChangeName() {
p.Name = "John"
}
func main() {
var max = Person{"Max", 23}
max.ChangeName() // or:
fmt.Println(max.Name)
}
This doesn’t change the name of the person, as a copy is passed.
Important: Keep in mind that max.ChangeName()
is just syncatical sugar for ChangeName(max)
if we were to rewrite the ChangeName
method slightly.
There, we need a way to change the value of the name actually: Using the memory address:
func (p *Person) ChangeName() {
p.Name = "John"
}
By just adding a *
in front, now a pointer is passed. Go automatically passes this pointer, but we can also manually pass it by: ChangeName(&max)
or declaring it as a reference.
Rewritten to a function:
func ChangeNameFun(p *Person) {
p.Name = "John"
}
func main() {
var max = Person{"Max", 23}
ChangeNameFun(&max)
fmt.Println(max.Name)
}
The only difference when using a function instead a method for the change is that we now need to pass the reference. This is explained in the next section.
Methods and pointer indirection
- Functions with a pointer parameter must take a pointer
- Methods with a pointer receiver can take either a value or a pointer
The same is true vice versa:
- Functions that expect a value, must receive a value of the type
- Methods with value receives can handle either a value or a pointer
Use pointer receivers in two cases:
- Accessing the value If you really direct need access to it, use a pointer receiver
- Avoiding copying Using values instead of pointer receivers always copy the value into the method. For huge chunks of data, this takes time. Pointers are the smarter way.
Next chapter: make() and new()