CodeNebula
Go🚀Advancedadvanced

The Go Memory Model

Go · Advanced · Run with go run

Explanation

The Go Memory Model specifies when a write by one goroutine is guaranteed to be visible to a read in another. The core rule: if you do not synchronize, you have no guarantee. Synchronization is established by channels (a send happens-before the corresponding receive completes), by mutexes (an `Unlock` happens-before a later `Lock`), by `sync.Once`, and by `sync/atomic`. The model exists so the compiler and CPU are free to reorder unsynchronized operations for speed.

Real-World Scenario

A goroutine sets a `ready` boolean and another goroutine spins waiting for it. Without synchronization the waiting goroutine may *never* observe the write — the compiler can hoist the read out of the loop, or the CPU can cache a stale value. Using a channel or `atomic.Bool` establishes the happens-before edge that makes the write visible.

Quick Snippet

snippet.go
// BROKEN — data race, no happens-before relationship
var ready bool
var data string
func setup() { data = "loaded"; ready = true }   // writes may be reordered
func wait()  { for !ready {}; print(data) }       // may see "" or never exit

// CORRECT — the channel send/receive synchronizes both writes
var done = make(chan struct{})
func setupOK() {
    data = "loaded"
    close(done) // send happens-before receive
}
func waitOK() {
    <-done       // after this, data's write is guaranteed visible
    print(data)  // always "loaded"
}

Full Example

memory_model.go
// Compile: go run memory_model.go
// Output:
//   data is visible: loaded
//
// The channel close below establishes a happens-before edge: the write
// to `data` is guaranteed visible to the goroutine that receives from
// the channel. Without that synchronization the read could see "".
package main

import "fmt"

var data string

func main() {
	done := make(chan struct{})

	go func() {
		data = "loaded"
		close(done) // send/close happens-before the receive
	}()

	<-done // after this, data's write is guaranteed visible
	fmt.Println("data is visible:", data)
}
Run command
go run memory_model.go