Methods
Prerequisites: Pointers
A method is a function attached to a type. The extra
parameter in parentheses before the name is the receiver —
the value the method is called on, similar to this or self
in other languages (but named like any other parameter).
Syntax
type Rectangle struct {
Width, Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
rect := Rectangle{Width: 3, Height: 4}
rect.Area() // 12
By convention the receiver name is a short abbreviation of the
type (r for Rectangle), not this or self.
Example
package main
import "fmt"
type Rectangle struct {
Width, Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func (r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}
func (r Rectangle) IsSquare() bool {
return r.Width == r.Height
}
// Grow has a value receiver, so it only changes a copy.
func (r Rectangle) Grow(amount float64) {
r.Width += amount
r.Height += amount
}
// Methods work on any type you define, not just structs.
type Celsius float64
func (c Celsius) Fahrenheit() float64 {
return float64(c)*9/5 + 32
}
func main() {
rect := Rectangle{Width: 3, Height: 4}
fmt.Println(rect.Area())
fmt.Println(rect.Perimeter())
fmt.Println(rect.IsSquare())
rect.Grow(10)
fmt.Println(rect.Width)
temp := Celsius(100)
fmt.Println(temp.Fahrenheit())
}
Expected output
12
14
false
3
212
All the methods above use a value receiver (r Rectangle):
each call works on a copy of the struct. That's perfect for
methods that only read fields, and it explains why Grow had no
effect — rect.Width is still 3. Methods that need to modify
the receiver use a pointer receiver (r *Rectangle); those
are covered in Level 2, together with interfaces.
Common mistakes
- Writing a value-receiver method that assigns to fields and expecting the change to stick.
- Trying to add methods to a type from another package (such as
intorstringdirectly). Define your own type first, liketype Celsius float64. - Mixing up
rect.Area(the method value) andrect.Area()(the call).
Practice
Define a Circle struct with a Radius float64 field and an
Area() method using math.Pi. Print the area of a circle with
radius 2, formatted to two decimal places.
Show solution
package main
import (
"fmt"
"math"
)
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return math.Pi * c.Radius * c.Radius
}
func main() {
c := Circle{Radius: 2}
fmt.Printf("%.2f\n", c.Area()) // 12.57
}