...

/

Introduction to Methods

Introduction to Methods

So far in this course, you have studied and used functions. This lesson brings a new concept of Go similar to functions but slightly different, i.e., methods.

We'll cover the following...

What is a method?

Structs look like a simple form of classes, so an OO programmer might ask, where are the methods of the class? Again, Go has a concept with the same name and roughly the same meaning. A Go method is a function that acts on a variable of a certain type, called the receiver. Therefore, a method is a special kind of function.

Note: A method acting on a variable in Go is similar to the object of a class calling its function in other OO languages, using a . selector, e.g., object.function().

The receiver type can be (almost) anything, not only a struct type. Any type can have methods, even a function type or alias types for int, bool, string, or array. However, the receiver cannot be an interface type since an interface is an abstract definition and a method is the implementation. Trying to do so generates the compiler error: invalid receiver type.

Lastly, a method cannot be a pointer type, but it can be a pointer to any of the allowed types. The combination of a (struct) type and its methods is the Go equivalent of a class in OO. One important difference is that the code for the type and the methods binding to it are not grouped together. They can exist in different source files; the only requirement is that they have to be in the same package.

The collection of all the methods on a given type T (or *T) is called the method set of T (or *T).

Methods are functions, so again, there is no method overloading, which means for a given type, there is only one method with a given name. However, based on the receiver type, there is overloading. A method with the same name can exist on two or more different receiver types, e.g., this is allowed in the same package:

func (a *denseMatrix) Add(b Matrix) Matrix
func (a *sparseMatrix) Add(b Matrix) Matrix

An alias of a certain type can’t redefine the methods defined on that type because an alias is the same as the original type. However, a new type based on a type can redefine these methods.

This is illustrated in the following example:

package main
import "fmt"

type S struct {
  a int
}

type SType S // New type
type SAlias = S // Alias
type IntType int // New type
type IntAlias = int // Alias

func (recv S) print() { // function for type defined on type S
  fmt.Printf("%t: %[1]v\n", recv)
}
func (recv SType) print() { // function for type defined on the basis of S
  fmt.Printf("%t: %[1]v\n", recv)
}

// func (recv SAlias) print() { // <-- error: S.print redeclared in this block previous declaration at ./struct_method.go:15:6
// fmt.Printf("%t: %[1]v\n", recv)
// }

func (recv IntType) print() { // function for type defined on type on the basis of int
  fmt.Printf("%t: %[1]v\n", recv)
}

// func (recv IntAlias) print() { // <-- error: cannot define new methods on non-local type int
// fmt.Printf("%t: %[1]v\n", recv)
// }

func main(){
  a := S{10}
  a.print() // calling function from line 13
  b := SType{20}
  b.print() // calling function from line 16
  c := SAlias{30}
  c.print() // calling function from line 13
  d := IntType(40)
  d.print() // calling function from line 24
  // e := IntAlias(50) <-- error: e.print undefined (type int has no field or method print)
  // e.print()
}

Click the RUN button and wait for the terminal to start. Type go run main.go and press ENTER. In case you make any changes to the file, you ...