Challenge 3 - Compiler
- Go course
- Expert
- Lesson 33/34
- 8 min
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.
Practice 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.
Starter code
package main
import (
"fmt"
"testing"
)
func main() {
// buraya yaz
}Sample 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)
}Expected output
0 true
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 Why does returning a small struct by value not allocate?
- The value is copied to the caller's stack and doesn't escape Correct answer
- The GC doesn't see it
- The compiler removes the struct
- Pointers are always slow
Explanation: When a copy is returned, the local variable isn't needed after the function, so escape analysis keeps it on the stack.
2 Value receiver
func (p ____) Topla(q Nokta) Nokta {
return Nokta{p.X + q.X, p.Y + q.Y}
}
func (p Nokta) Topla(q Nokta) Nokta {
return Nokta{p.X + q.X, p.Y + q.Y}
}
Explanation: A value receiver works on a copy of the struct; for small types it avoids heap allocation.
3 Type and choice
| Term | Meaning |
|---|---|
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 |