go · level 3 · unit 4 · lesson 4
- meet it
- guess first
- your turn
- fix it
- nailed it
Tap a green word if you get lost.
meet it
Let one goroutine own the data, and send it requests.
A Go proverb says: do not communicate by sharing memory; share memory by communicating. Instead of many goroutines locking one map, hand the map to a single goroutine. Nobody else touches it, ever. Keeping data inside one goroutine like this is called .
Others send that owner requests on a channel. A request that needs an answer carries its own : the owner does the work and sends the result back on it. Only the owner touches the data, so there is nothing to lock and nothing to race.
A mutex is fine for small shared state. An owner shines when the state has rules, or many steps that must happen in order.
package main
import "fmt"
type order struct {
item string
reply chan int
}
func keeper(orders chan order) {
stock := map[string]int{"apples": 5, "pears": 2}
for o := range orders {
stock[o.item]--
o.reply <- stock[o.item]
}
}
func main() {
orders := make(chan order)
go keeper(orders)
for _, item := range []string{"apples", "pears", "apples"} {
reply := make(chan int)
orders <- order{item: item, reply: reply}
fmt.Println(item, "left:", <-reply)
}
} The stock map lives inside keeper, so no other goroutine could reach it even by mistake.
guess first
Four goroutines send to one owner. What is the total?
Guess before you run it. Wrong guesses are how you learn, and nothing is marked.
package main
import (
"fmt"
"sync"
)
func counter(adds chan int, total chan int) {
sum := 0
for n := range adds {
sum += n
}
total <- sum
}
func main() {
adds, total := make(chan int), make(chan int)
go counter(adds, total)
var wg sync.WaitGroup
for i := 1; i <= 4; i++ {
wg.Add(1)
go func(n int) { defer wg.Done(); adds <- n }(i)
}
wg.Wait()
close(adds)
fmt.Println(<-total)
}
your turn
Your turn. Ask the guest list keeper.
Fill in the field the keeper answers on, choose a second guest to ask about, and receive the answer in the Println.
output
press run to see what happens
fix it
Everyone waits and nobody answers. Can you fix it?
output
press run to see what happens
- The keeper is stuck sending and
mainis stuck receiving. Are they using the same channel? - The order never carries
reply, so itsreplyfield is a nil channel, and sending on nil waits forever. - Send
order{item: item, reply: reply}.
nailed it
your data has one owner and no races. :D
- Share memory by communicating, not by locking everything.
- One goroutine owns the data; others send it requests.
- A reply channel inside a request brings the answer back.
new words in your collection
- confinement
- reply channel
This lesson isn’t saved. A free account remembers every lesson you finish.