DMarlon Studio

Lesson 15 · 15 of 20

Methods · Go

Add methods to your own Go types: value and pointer receivers, and the String() method that decides how a value is printed.

Go · Methods in DMarlon Studio: the example's code and its output in the terminal

A method is a function attached to a type. It is written like a function, but with a receiver in parentheses before the name: func (r Room) Area() float64. Inside, r is the room it was called on, and you call it with the dot: flat[i].Area().

With a value receiver, (r Room), the method gets a copy, which is enough for reading, as in Area. To change the original room you need a pointer receiver, (r *Room): Extend makes the bathroom one metre longer, from 2.5 to 3.5. When you call flat[2].Extend(1), Go passes the address for you; the next lesson explains pointers.

If a type has a String() string method, fmt uses it to print it. That is why %v shows Kitchen 3.0 x 4.5 m instead of {Kitchen 3 4.5}. The method itself builds that text with fmt.Sprintf.

The for walks through the flat, prints each room with its area and adds them up: 34.50 m². Go has no classes: a struct with its methods plays that role.

Code · main.go

package mainimport "fmt"type Room struct {	Name          string	Width, Length float64}// A method has a receiver before its name: (r Room).func (r Room) Area() float64 {	return r.Width * r.Length}// A pointer receiver (*Room) can change the original room.func (r *Room) Extend(meters float64) {	r.Length += meters}// String() decides how fmt prints a Room.func (r Room) String() string {	return fmt.Sprintf("%-8s %.1f x %.1f m", r.Name, r.Width, r.Length)}func main() {	flat := []Room{{"Kitchen", 3, 4.5}, {"Bedroom", 3.5, 4}, {"Bath", 2, 2.5}}	flat[2].Extend(1) // Go passes &flat[2] for us	total := 0.0	for i := 0; i < len(flat); i++ {		fmt.Printf("%v -> %5.2f m2\n", flat[i], flat[i].Area())		total += flat[i].Area()	}	fmt.Printf("Whole flat: %.2f m2\n", total)}

Output · go run main.go

Kitchen  3.0 x 4.5 m -> 13.50 m2
Bedroom  3.5 x 4.0 m -> 14.00 m2
Bath     2.0 x 3.5 m ->  7.00 m2
Whole flat: 34.50 m2

Key points

  • A method has a receiver: func (r T) Name().
  • A value receiver works on a copy.
  • A pointer receiver, (r *T), changes the original.
  • String() string decides how fmt prints the type.

Exercise

Add a Perimeter() float64 method and a Rename(name string) method with a pointer receiver; rename the bedroom and print the perimeter of every room.