Learning Go’s Concurrency Through Illustrations

Trevor Forrey
May 16, 2018 · 11 min read

Single-threaded vs. Multi-threaded Programs

func main() {
theMine := [5]string{“rock”, “ore”, “ore”, “rock”, “ore”}
foundOre := finder(theMine)
minedOre := miner(foundOre)
smelter(minedOre)
}
From Finder: [ore ore ore]From Miner: [minedOre minedOre minedOre]From Smelter: [smeltedOre smeltedOre smeltedOre]

Go routines

func main() {
theMine := [5]string{“rock”, “ore”, “ore”, “rock”, “ore”}
go finder1(theMine)
go finder2(theMine)
<-time.After(time.Second * 5) //you can ignore this for now
}
Finder 1 found ore!
Finder 2 found ore!
Finder 1 found ore!
Finder 1 found ore!
Finder 2 found ore!
Finder 2 found ore!

Channels

myFirstChannel := make(chan string)
myFirstChannel <- "hello" // Send
myVariable := <- myFirstChannel // Receive
func main() {
theMine := [5]string{“ore1”, “ore2”, “ore3”}
oreChan := make(chan string)
// Finder
go func(mine [5]string) {
for _, item := range mine {
oreChan <- item //send
}
}(theMine)
// Ore Breaker
go func() {
for i := 0; i < 3; i++ {
foundOre := <-oreChan //receive
fmt.Println(“Miner: Received “ + foundOre + “ from finder”)
}
}()
<-time.After(time.Second * 5) // Again, ignore this for now
}
Miner: Received ore1 from finderMiner: Received ore2 from finderMiner: Received ore3 from finder

Channel Blocking

Blocking on a Send

Blocking on a Receive

Unbuffered Channels

Buffered Channels

bufferedChan := make(chan string, 3)
bufferedChan := make(chan string, 3)go func() {
bufferedChan <- "first"
fmt.Println("Sent 1st")
bufferedChan <- "second"
fmt.Println("Sent 2nd")
bufferedChan <- "third"
fmt.Println("Sent 3rd")
}()
<-time.After(time.Second * 1)go func() {
firstRead := <- bufferedChan
fmt.Println("Receiving..")
fmt.Println(firstRead)
secondRead := <- bufferedChan
fmt.Println(secondRead)
thirdRead := <- bufferedChan
fmt.Println(thirdRead)
}()
Sent 1st
Sent 2nd
Sent 3rd
Receiving..
first
second
third

Putting it all Together

theMine := [5]string{"rock", "ore", "ore", "rock", "ore"}
oreChannel := make(chan string)
minedOreChan := make(chan string)
// Finder
go func(mine [5]string) {
for _, item := range mine {
if item == "ore" {
oreChannel <- item //send item on oreChannel
}
}
}(theMine)
// Ore Breaker
go func() {
for i := 0; i < 3; i++ {
foundOre := <-oreChannel //read from oreChannel
fmt.Println("From Finder: ", foundOre)
minedOreChan <- "minedOre" //send to minedOreChan
}
}()
// Smelter
go func() {
for i := 0; i < 3; i++ {
minedOre := <-minedOreChan //read from minedOreChan
fmt.Println("From Miner: ", minedOre)
fmt.Println("From Smelter: Ore is smelted")
}
}()
<-time.After(time.Second * 5) // Again, you can ignore this
From Finder:  oreFrom Finder:  oreFrom Miner:  minedOreFrom Smelter: Ore is smeltedFrom Miner:  minedOreFrom Smelter: Ore is smeltedFrom Finder:  oreFrom Miner:  minedOreFrom Smelter: Ore is smelted

Before you go, you should know..

Anonymous Go Routines

// Anonymous go routine
go func() {
fmt.Println("I'm running in my own go routine")
}()

The main function is a go routine

<-time.After(time.Second * 5) //Receiving from channel after 5 sec
func main() {
doneChan := make(chan string)
go func() {
// Do some work…
doneChan <- “I’m all done!”
}()

<-doneChan // block until go routine signals work is done
}

You can range over a channel

 // Ore Breaker
go func() {
for foundOre := range oreChan {
fmt.Println(“Miner: Received “ + foundOre + “ from finder”)
}
}()

You can make a non-blocking read on a channel

myChan := make(chan string)

go func(){
myChan <- “Message!”
}()

select {
case msg := <- myChan:
fmt.Println(msg)
default:
fmt.Println(“No Msg”)
}
<-time.After(time.Second * 1)select {
case msg := <- myChan:
fmt.Println(msg)
default:
fmt.Println(“No Msg”)
}
No Msg
Message!

You can also do non-blocking sends on a channel

select {
case myChan <- “message”:
fmt.Println(“sent the message”)
default:
fmt.Println(“no message sent”)
}

Where to learn next

Trevor Forrey

Written by

I'm a master's software engineering student at ASU. I love learning about new tech along with combining art with programming. @tforrey

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade