Go
Challenge 3 - Compiler
Write a tool that inspects escape and inline decisions.
Challenge: prevent escapes
A geometry library returns pointers from every computation:
type Nokta struct{ X, Y float64 }
func yeniNokta(x, y float64) *Nokta { return &Nokta{x, y} }
func (p *Nokta) Topla(q *Nokta) *Nokta { return &Nokta{p.X + q.X, p.Y + q.Y} }
Every call escapes an object to the heap. For a small 16-byte struct, value semantics are both faster and allocation-free. Your task: rewrite the API to work with values and measure the difference.
When to use pointers
A pointer receiver is needed when the value is large (hundreds of bytes), the object is to be modified, it has fields that must not be copied (sync.Mutex), or identity matters. For small, immutable data (a point, a color, a money amount, a time), value semantics are preferred; time.Time is the standard library's example.
Exercise Value semantics
Rewrite Nokta with a Topla that works on values. Measure p = p.Topla(Nokta{1, 1}) inside testing.AllocsPerRun; print the result and p.X after 10 steps.
Show example solution
package main
import (
"fmt"
"testing"
)
type Nokta struct{ X, Y float64 }
func (p Nokta) Topla(q Nokta) Nokta { return Nokta{p.X + q.X, p.Y + q.Y} }
func main() {
var p Nokta
a := testing.AllocsPerRun(10, func() { p = p.Topla(Nokta{1, 1}) })
fmt.Println(a, p.X >= 10)
}
Test yourself
-
Why does returning a small struct by value not allocate?
- The value is copied to the caller's stack and doesn't escape
- The GC doesn't see it
- The compiler removes the struct
- Pointers are always slow
Show answer
The value is copied to the caller's stack and doesn't escape — When a copy is returned, the local variable isn't needed after the function, so escape analysis keeps it on the stack.
-
Value receiver
func (p ____) Topla(q Nokta) Nokta {
return Nokta{p.X + q.X, p.Y + q.Y}
}
Show answer
func (p Nokta) Topla(q Nokta) Nokta {
return Nokta{p.X + q.X, p.Y + q.Y}
}
-
Type and choice
- Nokta (16 B)
- Value: cheap copy
- Type containing a mutex
- Pointer: must not be copied
- Large buffer (4 KB)
- Pointer: copying is expensive
- time.Time
- Value: immutable data
Next lesson: Challenge 4 - Production runtime