intermediate20 min

Structs and Methods

Defining custom types with struct, and attaching behavior with methods and receivers.

What you'll learn

  • Define a custom type with `struct` and create instances of it
  • Attach a method to a struct type using a receiver
  • Explain when a pointer receiver is needed instead of a value receiver

Explanation

Go doesn't have classes -- instead, you define a custom data shape with struct: type Point struct { X, Y int }, then create instances with Point{X: 3, Y: 4}.

You attach behavior to a struct with a method: a function with a special receiver parameter before its name, e.g. func (p Point) String() string { return fmt.Sprintf("(%d, %d)", p.X, p.Y) }. Here (p Point) is the receiver -- inside the method, p refers to the specific instance the method was called on.

A receiver can be a value receiver ((p Point), gets a copy) or a pointer receiver ((p *Point), gets a reference to the original). Use a pointer receiver whenever the method needs to modify the struct -- a value receiver's changes only affect its local copy and are lost once the method returns.

Go automatically takes the address of a variable when calling a pointer-receiver method on it, so you can usually call myPoint.Scale(2) directly even if Scale has a pointer receiver, without writing (&myPoint).Scale(2) yourself.

Guided lab

Predict: A struct with value vs pointer receivers

GoNot executed
This lab does not run in your browser or on VisaSparkSchools's servers. Read the code, predict what it does, then reveal the real expected output.

Read this program and predict exactly what it prints.

package main

import "fmt"

type Counter struct {
	value int
}

func (c Counter) IncrementCopy() {
	c.value++
}

func (c *Counter) IncrementReal() {
	c.value++
}

func main() {
	c := Counter{value: 0}
	c.IncrementCopy()
	fmt.Println("After IncrementCopy:", c.value)

	c.IncrementReal()
	fmt.Println("After IncrementReal:", c.value)
}

Stuck? Get a hint.

Common mistakes

  • Using a value receiver on a method meant to modify the struct, then being confused when the change doesn't persist outside the method.
  • Assuming Go structs work exactly like classes with inheritance -- Go has no inheritance; behavior is attached via methods and composition instead.
  • Forgetting that a value receiver method gets a full copy of the struct, which can matter for large structs and performance, not just mutability.

Knowledge check

Knowledge check

1. When must you use a pointer receiver instead of a value receiver?
2. What does a value receiver method operate on?
3. Does Go support class-style inheritance for structs?

Takeaway

Use a pointer receiver whenever a method needs to modify the struct persistently -- a value receiver only ever changes its own local copy.

Summary

Structs define custom data shapes; methods attach behavior via a receiver, which must be a pointer receiver for changes to persist outside the method.

References

Your notes

Notes save automatically.

Finished this lesson?

Mark it complete to track your progress and schedule a future review.

Next: Interfaces