Skip to content

Instantly share code, notes, and snippets.

@audstanley
Created July 21, 2021 17:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save audstanley/3be5904a020f38547a517ed1be13a51a to your computer and use it in GitHub Desktop.
Save audstanley/3be5904a020f38547a517ed1be13a51a to your computer and use it in GitHub Desktop.
go-channel-notes
package main
import (
"fmt"
"os"
"os/signal"
"strconv"
"sync"
"syscall"
"time"
)
// This funtion keeps running for 10 seconds.
// It also listens for signal interrupts, and closes the channel when detected
// The switch statment is non-blocking when waiting for a signal interrupt.
func timeRun(c chan<- string, wg *sync.WaitGroup, sigs chan os.Signal) {
defer wg.Done()
stop := false
for i := 0; i < 10 && !stop; i++ {
select {
case sig := <-sigs:
fmt.Print(sig, "detected, stopping channel")
stop = true
close(c)
os.Exit(0)
case c <- strconv.Itoa(i):
fmt.Println("sent:", strconv.Itoa(i))
// if we don't sleep here the non-blocking write to channel will loop too quickly
// which will cause the default channel to just print i, without sending to the channel
time.Sleep(time.Second * 1)
continue
default:
// if we were to write to channel in the defualt switch statement [c <- strconv.Itoa(i)],
// it would block if the receiver closed. (fine... if we are NOT closing the receiver)
// but the receiver might need close due to a signal interrupt -
// though in this code.. we are running os.Exit(0) if either channel listeners get the signal interrupt
// first [because, yes, having two receivers - both are indeterminate on which will receive the sigint]
fmt.Println("default. sent:", strconv.Itoa(i))
time.Sleep(time.Second * 1)
continue
}
}
fmt.Println("for loop finished")
if !stop {
close(c)
}
return
}
// This will basically take strings from the string channel, and print.
// for the sake of testing, we'll stop printing from the when the nextThing
// function detects the string "5".
func nextThing(c chan string, wg *sync.WaitGroup, sigs chan os.Signal) {
defer wg.Done()
fmt.Println("waiting for message")
stop := false
for !stop {
select {
case sig := <-sigs:
fmt.Println(sig, ": stopping message printer")
stop = true
os.Exit(0)
default:
msg := <-c
fmt.Println("message:", msg)
if msg == "5" {
fmt.Println("got five")
stop = true
}
time.Sleep(time.Second * 1)
}
}
fmt.Println("stopping message printer")
return
}
func main() {
var wg sync.WaitGroup
wg.Add(2)
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, os.Interrupt, syscall.SIGTERM)
c := make(chan string)
// we are concurrently calling these functions.
go timeRun(c, &wg, sigs)
go nextThing(c, &wg, sigs)
fmt.Println("done")
wg.Wait()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment