Single goroutine excution order

The compiler and processors may reorder the read and write exectuted within a single goroutine only when the reordering does not change the behaviour within that goroutine as defined by language specifiction.

E.g: if one goroutine executes a = 1; b = 2;, other might observe update of b before update of a.

var a, b int

func f() {
	a = 1
	b = 2
}

func g() {
	print(b)
	print(a)
}

func main() {
	go f()
	g()
}

g() can print 2 then 0.

A send or close on channel happens before corresponding receive from that channel completes.
var c = make(chan int, 10)
var a string

func f() {
	a = "hello, world"
	c <- 0
}

func main() {
	go f()
	<-c
	print(a)
}

guarantee to print "hello, world"

A receive from an unbuffered channel happends before the send on that channel completes
var c = make(chan int)
var a string

func f() {
	a = "hello, world" # (1)
	<-c # (2)
}

func main() {
	go f()
	c <- 0 # (3)
	print(a) # (4)
}
unbuffered channel
The kth receive on a channel with capacity C happens before the k+Cth send from that channel completes.
var limit = make(chan int, 3)

func main() {
	for _, w := range work {
		go func(w func()) {
			limit <- 1
			w()
			<-limit
		}(w)
	}
	select{}
}

this program ensures there are at most 3 running work functions at a time.