Go Methods

Summary: in this tutorial, you will learn about Go methods, which allow you to define methods on types including structs.

Go methods allow you to define functions on types including structs. By definition, Go methods are functions with a receiver argument.

Here’s the syntax for defining a method:

func (r receiverType) methodName(parameters) returnType {
    // method body
}Code language: Go (go)

In this syntax, you place the receiver argument between the func keyword and method name. The rest is the same as the syntax for defining a function.

Go method example

Step 1. Define a Rectangle struct that has length and width fields:

type Rectangle struct {
    length float64
    width  float64
}Code language: Go (go)

Step 2. Create a function that calculates the area of a Rectangle struct:

func Area(r Rectangle) float64 {
    return r.length * r.width
}Code language: Go (go)

Step 3. Create a Rectangle struct value, calculate the area, and display the result on the screen:

func main() {
    r := Rectangle{length: 10, width: 5}
    fmt.Println("Area of rectangle is", Area(r))
}Code language: Go (go)

Here’s the complete program:

package main

import "fmt"

type Rectangle struct {
    length float64
    width  float64
}

func Area(r Rectangle) float64 {
    return r.length * r.width
}

func main() {
    r := Rectangle{length: 10, width: 5}
    fmt.Println("Area of rectangle is", Area(r))
}Code language: Go (go)

Output:

Area of rectangle is 50Code language: Go (go)

The program works fine. But it’s more intuitive if we can call the Area() function like this:

r.Area()Code language: Go (go)

To do this, we can define the Area() function as a method of the Rectangle struct type.

Step 4. Change the Area() function to a method:

func (r Rectangle) Area() float64 {
    return r.length * r.width
}Code language: Go (go)

In this example:

  • First, specify the receiver argument (r Rectangle) between the func keyword and Area method name.
  • Second, remove parameters from the Area() function because we can access the length and width field via the r parameter.

The Area() function becomes a method of the Rectangle struct type.

Here’s the updated program:

package main

import "fmt"

type Rectangle struct {
    length float64
    width  float64
}

func (r Rectangle) Area() float64 {
    return r.length * r.width
}

func main() {
    r := Rectangle{length: 10, width: 5}
    fmt.Println("Area of rectangle is", r.Area())
}Code language: Go (go)

Define receivers as pointers

Like functions, methods use the pass-by-value mechanism. This means that methods copy arguments and work on the copied versions inside their body. Any changes methods make to the arguments will not be reflected in the original arguments.

Therefore, if you want to change the fields of a struct inside methods, you need to use a pointer to the struct as the receiver.

For example, the following defines the Scale() method of the Rectangle struct. It uses a pointer as a receiver:

func (r *Rectangle) Scale(factor float64) {
    r.length *= factor
    r.width *= factor
}Code language: Go (go)

In this example, the Scale method changes both the length and width fields of the rectangle. You may wonder why we can access them using this syntax:

r.length
r.widthCode language: Go (go)

But not using the correct syntax:

(*r).length
(*r).widthCode language: Go (go)

This is possible due to the automatic dereferencing feature in GO.

Go allows you to access struct fields through a pointer without explicitly dereferencing the pointer.

When the Go compiler compiles the code, it will automatically convert r.width to (*r).width for you, making the syntax more convenient and easier to read.

Here’s the updated program that includes the Scale() method:

package main

import "fmt"

type Rectangle struct {
    length float64
    width  float64
}

func (r Rectangle) Area() float64 {
    return r.length * r.width
}

func (r *Rectangle) Scale(factor float64) {
    r.length *= factor
    r.width *= factor
}

func main() {
    r := Rectangle{length: 10, width: 5}
    r.Scale(10)
    fmt.Println(r)
}Code language: Go (go)

Output:

{100 50}

Summary

  • Methods are functions with a receiver argument.
  • Use a pointer to the struct as a receiver to modify the struct fields inside methods.
Was this tutorial helpful?