Skip to content

Instantly share code, notes, and snippets.

@zeddee
Last active December 27, 2019 10:09
Show Gist options
  • Save zeddee/8bbdfa93f10dc1f129adbde6182f8e6c to your computer and use it in GitHub Desktop.
Save zeddee/8bbdfa93f10dc1f129adbde6182f8e6c to your computer and use it in GitHub Desktop.
// todo:
// - send 3 "pings" concurrently
// - receive the pings and store them in a slice called "msgbox"
// - print the contents of the "msgbox" -- it should contain 3 "ping" strings
package main
import (
"fmt"
"sync"
)
func main() {
wg := &sync.WaitGroup{}
messages := make(chan string)
msgbox := make([]string, 0)
// ping 3 times
for i := 0; i < 3; i++ {
go pinger(wg, messages, i)
}
// important! prevents deadlock!
go monitor(wg, messages)
// set 'done' as a channel that expects
// an empty struct (`struct{}`), which
// doesn't occupy memory and acts as
// a 'pure' signaller i.e. no values
// or bytes moved, therefore not allocations
// and does not occupy memory.
done := make(chan struct{})
go listener(messages, &msgbox, done)
// blocks the rest of the program from executing
// until we receive on the 'done' channel.
<-done
close(done)
fmt.Printf("Messages: %+v\n", msgbox)
fmt.Println("Message length:", len(msgbox))
}
// chan<- <type> denotes a send-only channel
func pinger(wg *sync.WaitGroup, messages chan<- string, count int) {
wg.Add(1) // increments wg counter
defer wg.Done() // decremenets wg counter
messages <- fmt.Sprintf("ping_%d", count)
fmt.Printf("sending ping %d\n", count)
}
// important! prevents deadlock!
func monitor(wg *sync.WaitGroup, m chan string) {
wg.Wait()
close(m)
}
// <-chan <type> denotes a receive-only channel
func listener(m <-chan string, msgbox *[]string, done chan<- struct{}) {
for i := range m {
func() {
// didn't realise that by calling 'i',
// we're consuming the message in chan 'm'
// therefore leaving an empty channel the next
// times we call it.
// using the value 'i', which has already
// stored the message received from chan 'm'
// fixes this bug
fmt.Printf("message %s received\n", i)
*msgbox = append(*msgbox, i)
fmt.Println("Current inbox:", msgbox)
defer func() { _ = recover() }()
}()
}
// this lets us introduce a 'done` channel in main() that blocks
// the program from exiting until the channel is empty.
done <- struct{}{}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment