Last active
December 27, 2019 10:09
-
-
Save zeddee/8bbdfa93f10dc1f129adbde6182f8e6c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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