Function declaration syntax: things in parenthesis before function name

If you are familiar with c# extension methods,

a go method (a function with a special receiver argument) e.g.

func (v Vertex) Abs() float64

is similar to c# extension method

static float Abs( this Vertex v);

The differences between value types and pointers are described in evanmcdonnal’s answer


It means ServeHTTP is not a standalone function. The parenthesis before the function name is the Go way of defining the object on which these functions will operate. So, essentially ServeHTTP is a method of type handler and can be invoked using any object, say h, of type handler.

h.ServeHTTP(w, r)

They are also called receivers. There are two ways of defining them. If you want to modify the receiver use a pointer like:

func (s *MyStruct) pointerMethod() { } // method on pointer

If you dont need to modify the receiver you can define the receiver as a value like:

func (s MyStruct)  valueMethod()   { } // method on value

This example from Go playground demonstrates the concept.

package main

import "fmt"

type Mutatable struct {
    a int
    b int
}

func (m Mutatable) StayTheSame() {
    m.a = 5
    m.b = 7
}

func (m *Mutatable) Mutate() {
    m.a = 5
    m.b = 7
}

func main() {
    m := &Mutatable{0, 0}
    fmt.Println(m)
    m.StayTheSame()
    fmt.Println(m)
    m.Mutate()
    fmt.Println(m)

The output of the above program is :

&{0 0}
&{0 0}
&{5 7}

This is called the 'receiver'. In the first case (h handler) it is a value type, in the second (s *GracefulServer) it is a pointer. The way this works in Go may vary a bit from some other languages. The receiving type, however, works more or less like a class in most object-oriented programming. It is the thing you call the method from, much like if I put some method A inside some class Person then I would need an instance of type Person in order to call A (assuming it's an instance method and not static!).

One gotcha here is that the receiver gets pushed onto the call stack like other arguments so if the receiver is a value type, like in the case of handler then you will be working on a copy of the thing you called the method from meaning something like h.Name = "Evan" would not persist after you return to the calling scope. For this reason, anything that expects to change the state of the receiver needs to use a pointer or return the modified value (gives more of an immutable type paradigm if you're looking for that).

Here's the relevant section from the spec; https://golang.org/ref/spec#Method_sets

Tags:

Go