Methods

suggest change

A method is a function tied to a type, usually a struct but it works with any type.

This is similar to classes in languages like Java or C++.

Basics of methods:

type Person struct {
	FirstName string
	LastName  string
}

func (p *Person) PrintFullName() {
	fmt.Printf("%s %s\n", p.FirstName, p.LastName)
}

func main() {
	p := &Person{
		"John",
		"Doe",
	}
	p.PrintFullName()
}
John Doe

The instance on which the method operates is called a receiver.

In the above example method PrintFullName takes a receiver p whose type is *Person.

People coming from other languages are tempted to name the receiver this (mimicking C++) or self (mimicking Python). That is bad style in Go.

In Go, the rule for naming receiver is:

Value vs. pointer receiver

Method receiver can be either a value or a pointer.

As a convenience, the Go allows calling a pointer receiver on a value and calling a value receiver on a pointer:

type Person struct {
	FirstName string
	LastName  string
}

func (p Person) PrintFullNameValue() {
	fmt.Printf("PrintFullNameValue:   address of p is %p\n", &p)
}

func (p *Person) PrintFullNamePointer() {
	fmt.Printf("PrintFullNamePointer: p is            %p\n", p)
}

func main() {
	p := Person{
		"John",
		"Doe",
	}
	fmt.Printf("address of p:                         %p\n", &p)
	p.PrintFullNamePointer()
	p.PrintFullNameValue()

	pp := &p
	fmt.Printf("\naddress of pp:                        %p\n", pp)
	pp.PrintFullNamePointer()
	pp.PrintFullNameValue()	
}
address of p:                         0xc00000c060
PrintFullNamePointer: p is            0xc00000c060
PrintFullNameValue:   address of p is 0xc00000c080

address of pp:                        0xc00000c060
PrintFullNamePointer: p is            0xc00000c060
PrintFullNameValue:   address of p is 0xc00000c0a0

A value receiver is called on a copy of a value:

type Foo struct {
	Str string
}

func (f Foo) Print() {
	fmt.Printf("Value of Str inside Print: '%s'\n", f.Str)
	fmt.Printf("Address of &f  inside Print: 0x%p\n", &f)
	f.Str = "changed"
}

func main() {
	fv := Foo{
		Str: "Foo",
	}
	fv.Print()
	fmt.Printf("Address of &fv before Print: 0x%p\n", &fv);
	fmt.Printf("Value of Str after Print: '%s'\n", fv.Str)
}
Value of Str inside Print: 'Foo'
Address of &f  inside Print: 0x0xc000010220
Address of &fv before Print: 0x0xc000010210
Value of Str after Print: 'Foo'

You can see above the consequences of calling value receiver on a copy of a value:

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you:



Table Of Contents