Patterns: concurrent Go · 3 MIN READ
Single owner: serialize state through messages
Use one goroutine to own mutable state and define request completion.
Use one goroutine to own mutable state and define request completion. An actor-like owner serializes access to its state through messages. Trace the worked Go example, then compare the benefit with the cost before applying this design to your own project.
Concurrent Go pattern · A MAP OF THE IDEA
- Caller sends an explicit request
- One goroutine mutates its private state
- Reply and done signals establish completion
Useful when
- State transitions benefit from serial ownership
- Shutdown and command order should be explicit
Watch out
- Synchronous replies can strand the owner
- Mailbox capacity and overload need budgets
Implementation & operation cost: Medium
Fit depends on the task
Editorial suitability, not benchmarks or a universal ranking. Styles describe different axes and can be combined.
The design decision
An actor-like owner serializes access to its state through messages. This can make mutation and ordering explicit, but a Go channel does not automatically provide actor supervision, durability or remote messaging. A mutex is often simpler for a short shared-memory operation.
A complete Go example
Read this program from the entry point and follow the calls shown in the diagram. The output is included at the end so you can check the behavior without a compiler.
package main
import (
"fmt"
)
type Add struct {
Delta int
Reply chan int
}
func Counter(requests <-chan Add, done chan<- struct{}) {
defer close(done)
total := 0
for request := range requests {
total += request.Delta
request.Reply <- total
}
}
func main() {
requests := make(chan Add)
done := make(chan struct{})
go Counter(requests, done)
reply := make(chan int)
requests <- Add{Delta: 2, Reply: reply}
fmt.Println(<-reply)
requests <- Add{Delta: 3, Reply: reply}
fmt.Println(<-reply)
close(requests)
<-done
}
// Output:
// 2
// 5
Only Counter reads or writes total. Every request has a reply, so main knows when its change is applied, and done confirms shutdown. The caller must always receive the reply here; abandoned requests would require cancellation or a different response design.
Tradeoffs and the simpler alternative
Serialize only what needs one owner; a busy owner can become a bottleneck. Define mailbox capacity and overload behavior, and avoid a cycle of owners synchronously waiting for each other. Channel ownership and a mutex are alternatives chosen by the lifecycle, not by fashion.
TAKE THIS WITH YOU
Serializes mutation through one goroutine’s messages. Serialize only what needs one owner; a busy owner can become a bottleneck. Define mailbox capacity and overload behavior, and avoid a cycle of owners synchronously waiting for each other. Channel ownership and a mutex are alternatives chosen by the lifecycle, not by fashion.
Check your understanding
Which statement best describes Single owner: serialize state through messages?
Go to the source
Progress stays in this browser. No account needed.