Slices, maps and strings · 3 MIN READ
Shared slices and concurrent append
Separate shared headers, shared elements and safe collection of concurrent results.
A goroutine does not make its arguments private. If two workers share a slice, you must reason about the slice descriptor and the array it refers to. Making extra goroutines can expose an ownership mistake that a sequential example concealed.
Why append needs coordination
Concurrent append to one shared slice variable reads and writes the same descriptor and may write the same backing storage. Even if capacity is large enough, append still changes the shared length. Reserving capacity is a performance choice, not synchronization.
// Unsafe: both goroutines update the same slice.
var results []int
go func() { results = append(results, 1) }()
go func() { results = append(results, 2) }()The outcome is not a reliable permutation of [1 2]. This is a deliberate counterexample, not code to copy. A passing test without the race detector does not establish safety.
Give each worker a separate slot
A pre-sized slice permits independent element writes when each worker owns a different index, no worker changes the descriptor, and the reader waits for every writer. Elements that themselves contain shared pointers need their own ownership rules.
results := make([]int, len(inputs))
var wg sync.WaitGroup
for i, value := range inputs {
wg.Add(1)
go func(i, value int) {
defer wg.Done()
results[i] = value * 2
}(i, value)
}
wg.Wait() // Read results only after the writers finish.Index i is assigned to exactly one goroutine. WaitGroup orders the final read after the completed writes. For very large inputs, combine this ownership pattern with a bounded worker pool rather than starting a goroutine per item.
Use a single collector for variable-length output
If each job returns an unknown number of values, let workers send results to one owner that appends, or protect every access with the same mutex. A channel transfers values; it does not deep-copy a slice payload. The sender must stop mutating transferred storage or clone it first. Run race-enabled tests on a supported desktop toolchain; the app does not offer a native race detector.
TAKE THIS WITH YOU
Concurrency safety comes from ownership and synchronization, not spare capacity. Distinct indexes plus a final join differ from concurrent append.
Check your understanding
Which statement is correct about concurrent append?
Go to the source
Progress stays in this browser. No account needed.