Note of GoRoutines

Goroutines explain

in Go, each concurrently executing activity called a groutine

when a program starts, it has a groutine that calls the Main function, we call it _Main groutine_.

Goroutines have no notion of identity that is accessible to the programmer

Groutine Scheduling

the Go runtime contains its own scheduler that uses a technique known as m:n scheduling. because it multiplexes (or schedules) m goroutines on n OS threads. the job of the Go scheduler is analogous to that of the kernel scheduler. but it is concerned only with the goroutines of a single Go program.

Go scheduler is not invoked periodically by a hardware timer, for example, when a goroutine calls time.Sleep or blocks in a channel or mutex operation, the scheduler puts it to sleep and runs another goroutine until it is time to wake the first one up. rescheduling a groutine is much cheaper than rescheduling a thread.

goroutines that are sleeping or blocked in communication do not need a thread at all.


Go scheduler uses a parameter called GOMAXPROCS to determine how many OS threads may be actively executing Go code simultaneously. default value is the number of CPUs on the machine.

for {
go fmt.Print(0)
$ GOMAXPROCS=1 go run hacker-cliché.go
$ GOMAXPROCS=2 go run hacker-cliché.go

in the first run, at most one groutine was executed at a time. initially, it was the main groutine, which prints 1, after a period of time, the Go scheduler put it to sleep and woke up the goroutine that prints 0, giving it a turn to run on the OS thread.

Goroutine leak

when a goroutine gotten stuck,cause it’s trying to send their responses on a channel from which no goroutine will ever receive. this situation, called a goroutine leak

leak goroutines are not automatically collected, it's important to make sure that goroutines terminate themselves when no longer needed


when we cannot confidently say that one event happens before the other, then the events x and y are concurrent

concurency-safe: a function that works correctly in a sequential program even when called concurrently.

there are many reasons a function might not work when called concurrently, including deadlock / livelock / resource starvation.

Race Condition

a race condition is a situation in which the program does not give the correct result for some interleavings of the operations of multiple goroutines.

to avoice data race

  1. avoid accessing the variable from multiple groutines(channel)
  2. initialize variable before creating additional groutines, and never modify it again.

Groutine usage

f() // call f(); wait for it to return
go f() // create a new goroutine that calls f(); don't wait

Some details

  1. when Main function returns, all groutines will abruptly terminate
  2. apart of Main function returns, no other way to stop groutines


Channel explain

communication mechanism that lets one goroutine send values to another goroutine. connections between goroutines

Channel usage

ch := make(chan int) // unbuffered cahnnel
ch = make(chan int, 0) // unbuffered channel
ch = make(chan int, 3) // buffered channel with capacity 3
ch <- "data" // a send statement
x := <- ch // a receive expression in an assignment statement
<-ch // a rece expression; result is discarded
close(ch) // close channel that no more values will ever be sent on this channel

unbuffered channel

a send operation on an unbuffered channel blocks the sending goroutine until another goroutine executes a corresponding receive on the same channel.

unbuffered channels give stronger synchronization guarantees because every send operation is synchronized with its corresponding receive


Channels can be used to connect goroutines together so that the output of one is the input to another. this is called a pipeline

  1. Program will panic when Channel stop sending data but didn’t closed
  2. When Channel closed but receiver still receiving data, it will get empty data
  3. use range statement to receive data from a channel that will closed

Unidirectional Channel Types


Buffered Channels

buffered has a queue of elements. a send operation on a buffered channel interts an element at the back of the queue, also receive operation removes an element from the front. if the channel is full, the send operation blocks its goroutine until space is made available by another goroutines’s receive. Conversely, if the cahnnel is empty a receive operation blocks until a value is sent by another goroutine

buffered channels these operations between send / receive are decoupled, also got upper bound on the number of values that will be sent on a channel, failure to allocate sufficient buffer capacity would cause the program to dead lock

benfit of buffered channel


  • Add(int) add increments the counter
  • Done() equivalent Add(-1)

Mutual Exclusion Lock

var (
    mu sync.Mutex // lock


Leave a Reply

Your email address will not be published. Required fields are marked *