UP | HOME

Go: Methods

Table of Contents

1 Methods

A method is a function that has a defined receiver, in OOP terms, a method is a function on an instance of an object. The method receiver appears in its own argument list between the func keyword and the method name. The method on the User type could be defined anywhere in the package. In fact, you can define a method on any type you define in your package, not just structs. You cannot define a method on a type from another package, or on a basic type.

package main

import (
        "fmt"
)

type User struct {
        FirstName, LastName string
}


func (u User) Greeting() string {
        return fmt.Sprintf("Dear %s %s", u.FirstName, u.LastName)
}

func main() {
        u := User{"Matt", "Aimonetti"}
        fmt.Println(u.Greeting())
}
Dear Matt Aimonetti

2 Type aliasing

To define methods on a type you don’t “own”, you need to define an alias for the type you want to extend:

package main

import (
        "fmt"
        "strings"
        "math"
)

type MyStr string

func (s MyStr) Uppercase() string {
        return strings.ToUpper(string(s))
}

type MyFloat float64

func (f MyFloat) Abs() float64 {
        if f < 0 {
                return float64(-f)
        }
        return float64(f)
}

func main() {
        fmt.Println(MyStr("test").Uppercase())

        f := MyFloat(-math.Sqrt2)
        fmt.Println(f.Abs())
}
TEST
1.4142135623730951

3 Methods receivers

There are two reasons to use a pointer receiver.

  1. First, to avoid copying the value on each method call. Every time you call Greeting(), you are copying the User struct. Instead when using a pointer, only the pointer is copied

    package main
    
    import (
            "fmt"
    )
    
    type User struct {
            FirstName, LastName string
    }
    
    
    func (u *User) Greeting() string {
            return fmt.Sprintf("Dear %s %s", u.FirstName, u.LastName)
    }
    
    func main() {
            u := &User{"Pavel", "Vavilin"}
            fmt.Println(u.Greeting())
    }
    
    Dear Pavel Vavilin
    
    
  2. The other reason is so that the method can modify the value that its receiver points to.

    package main
    
    import (
            "fmt"
            "math"
    )
    
    type Vertex struct {
            X, Y float64
    }
    
    func (v *Vertex) Scale(f float64) {
            v.X = v.X * f
            v.Y = v.Y * f
    }
    
    func (v *Vertex) Abs() float64 {
            return math.Sqrt(v.X*v.X + v.Y*v.Y)
    }
    
    func main() {
            v := &Vertex{3, 4}
            v.Scale(5)
            fmt.Println(v, v.Abs())
    }
    
    &{15 20} 25
    
    

Author: Pavel Vavilin

Created: 2017-10-27 Fri 00:45

Validate