Starting a goroutine lets work proceed concurrently; it does not ensure that work finishes before the program exits. Synchronization coordinates goroutines so completion and access to shared data are deliberate rather than matters of timing. Incorrect coordination can produce intermittent race conditions or deadlocks. section 9.1 section 1.4
The RSS reader’s temporary wait
An RSS reader starts separate goroutines to fetch feed titles, then calls time.Sleep before exiting. The sleep makes the demonstration visible but cannot reliably establish that every fetch has completed. Replace that timing assumption with a way to track the goroutines’ completion. section 9.1 section 9.6.1
Listing 9.5 main.go: A second goroutine
func main() {
go printFeedTitle("https://rss.nytimes.com/services/xml/rss/nyt/World.xml")
go printFeedTitle("https://feeds.bbci.co.uk/news/
rss.xml") #1
fmt.Println("waiting....")
time.Sleep(15 * time.Second)
fmt.Println("stopped.")
}
The two-feed example shows the limitation: both fetches start independently, while main waits for a fixed 15 seconds rather than for their completion. section 9.1
Choose coordination according to what needs to be controlled:
- Pass data through channels when goroutines need to communicate; this also supports synchronization without relying on shared memory. section 1.4 section 9.6.1
- If goroutines must share data, protect it with sync.Mutex or sync.RWMutex to avoid races and preserve consistency. section 9.6.1
- Track completion with WaitGroup or errgroup rather than treating the go keyword as a completion mechanism. Handle errors explicitly, and use go test -race to check for races during development. section 9.6.1










