Go has no classes. Instead you bundle data into a struct — a group of named fields — and attach behavior to it from the outside, by writing functions with a receiver:
type Counter struct {
count int
}
func (c Counter) Inc() { // "(c Counter)" is the receiver
c.count++
}
The extra (c Counter) before the name turns a plain function into a method: you call it with dot syntax, c.Inc(), and inside the method c refers to the counter it was called on. That's the whole Go replacement for classes — struct for data, methods for behavior.
But there are TWO kinds of receiver, and picking the wrong one is the most famous silent bug in Go.
The trap: a value receiver gets a COPY.
With (c Counter) — a value receiver — the method receives a copy of your struct. It increments the copy, the copy is thrown away, and your counter never changes. No error, no warning:
c := Counter{count: 0}
c.Inc()
fmt.Println(c.count) // prints 0 — the ++ happened on a copy!
Write the receiver as a pointer instead — (c *Counter) — and the method receives the address of the ORIGINAL struct, so the mutation sticks. Calling it is no extra work: for a variable, Go automatically takes &c for you.
One thing Go will NOT do is take the address of a throwaway value. Call a pointer method directly on a struct literal and the compiler stops you:
Counter{count: 0}.IncP() // a literal has no address
cannot call pointer method IncP on Counter
Rule of thumb: if the method needs to CHANGE the struct, the receiver must be *T. If it only reads, a value receiver is fine.
Assignment
Follow the Coding Tutorial and catch the bug in the act:
- define
Counter, a struct with oneintfieldcount, - attach
Inc()with a value receiver(c Counter)that doesc.count++, - attach
IncP()with a pointer receiver(c *Counter)with the same body, - in
mainFunction, createc := Counter{count: 0}, callc.Inc()and print the count — it is still0, - call
c.IncP()and print again — now it is1.
The exact expected output is:
after Inc(): count = 0
after IncP(): count = 1
Hint
The two methods differ by a single character in the receiver: (c Counter) vs (c *Counter). That character decides whether the increment survives.
Free plan: 30 tutor messages. PRO is unlimited.
