68
votes

I am trying to get started with Go and the documentation is very good. What I did not find in the documentation is the difference between functions and methods.

As far as I understand at the moment: functions are "global", which means I do not have to import a package to use functions, they are always there. Methods are bound to packages. Is this correct?

3
The terms "method" and "function" are just historical conventions. The plain language implies "how" versus "what" which is not the case, and therefore confusing. We might believe "function" is mathematical, but that's also not the case, and therefore confusing. The truth is "method" was just adopted from OO languages as being associated with a particular type, while "function" was adopted from procedural languages where the function is free-standing. I think you can see those simple explanations hold in go: method is invoked on a type, function is not.Rick O'Shea

3 Answers

114
votes

As far as I understand at the moment: functions are "global", which means I do not have to import a package to use functions, they are always there. Methods are bound to packages. Is this correct?

No, that's not correct. There are just a couple of functions from the builtin package which are always available. Everything else needs to be imported.

The term "method" came up with object-oriented programming. In an OOP language (like C++ for example) you can define a "class" which encapsulates data and functions which belong together. Those functions inside a class are called "methods" and you need an instance of that class to call such a method.

In Go, the terminology is basically the same, although Go isn't an OOP language in the classical meaning. In Go, a function which takes a receiver is usually called a method (probably just because people are still used to the terminology of OOP).

So, for example:

func MyFunction(a, b int) int {
  return a + b
}
// Usage:
// MyFunction(1, 2)

but

type MyInteger int
func (a MyInteger) MyMethod(b int) int {
  return a + b
}
// Usage:
// var x MyInteger = 1
// x.MyMethod(2)
23
votes

Tux's answer is great, but I want to augment it with the usage of Go's methods with structs (because this is where I used it often). So let's assume you want to build something to calculate various methods on triangles. You start with a struct:

type Triangle struct {
    a, b, c float64
}

and then you would like to add some functions to calculate the perimeter and square:

func valid(t *Triangle) error {
    if t.a + t.b > t.c && t.a + t.c > t.b && t.b + t.c > t.a {
        return nil
    }
    return errors.New("Triangle is not valid")
}

func perimeter(t *Triangle) (float64, error) {
    err := valid(t)
    if err != nil {
        return -1, err
    }

    return t.a + t.b + t.c, nil
}

func square(t *Triangle) (float64, error) {
    p, err := perimeter(t)
    if err != nil {
        return -1, err
    }

    p /= 2
    s := p * (p - t.a) * (p - t.b) * (p - t.c)
    return math.Sqrt(s), nil
}

And now you got your working program Go Playground. In this case your function takes a parameter (pointer to a triangle) and does something. In OOP word people might have created a class and then added methods. We can see our struct as kind of class with fields and now we add methods:

func (t *Triangle) valid() error {
    if t.a + t.b > t.c && t.a + t.c > t.b && t.b + t.c > t.a {
        return nil
    }
    return errors.New("Triangle is not valid")
}

func (t *Triangle) perimeter() (float64, error) {
    err := t.valid()
    if err != nil {
        return -1, err
    }

    return t.a + t.b + t.c, nil
}

func (t *Triangle) square() (float64, error) {
    p, err := t.perimeter()
    if err != nil {
        return -1, err
    }

    p /= 2
    s := p * (p - t.a) * (p - t.b) * (p - t.c)
    return math.Sqrt(s), nil
}

and we have a fully working example.

Notice that it looks really like a method for objects.

13
votes

They are explained in detail here - https://anil.cloud/2017/01/26/golang-functions-methods-simplified/

A function in Go follows the syntax:

func FunctionName(Parameters...) ReturnTypes...

Example:

func add(x int, y int) int

To execute:

  add(2,3) 

A method is like a function, but attached to a type (called as receiver). The official guide states “A method is a function with a special receiver argument”. The receiver appears in between the func keyword and the method name. The syntax of a method is:

func (t ReceiverType) FunctionName(Parameters...) ReturnTypes...

Example:

func (t MyType) add(int x, int y) int

To execute:

type MyType string
t1 := MyType("sample")
t1.add(1,2)

Now lets bring pointers into the table. Go lang is pass by value, means fresh copies of the parameters are passed to each function/method call. To pass them by reference you can use pointers.

Syntax of function with pointer in argument/parameter list.

func FunctionName(*Pointers...,Parameters...) ReturnTypes...

Example

func add(t *MyType, x int, y int) int

To execute:

type MyType string
t1 := MyType("sample")
add(&t1,4,5)

Similarly for methods, the receiver type can be a pointer. Syntax of method with pointer (as receiver)

func (*Pointer) FunctionName(Parameters...) ReturnTypes...

Example

func (t *MyType) add(x int, y int) int

To execute:

type MyType string
t1 := MyType("sample")
t1.add(2,3)

Note that we can still write t1.add() to execute the method with a pointer receiver(even-though ‘t1’ is not a pointer) and Go will interpret it as (&t1).add(). Similarly a method with value receiver can be called using pointer too, Go will interpret p.add() as as (*p).add() in that case (where ‘p’ is a pointer). This is applicable only for methods and not for functions.

Methods with pointer receiver are very useful to get a “Java” like behavior where the method is actually modifying on the value to which the receiver points and not on a copy of it.