Created
July 21, 2021 17:07
-
-
Save audstanley/3be5904a020f38547a517ed1be13a51a to your computer and use it in GitHub Desktop.
go-channel-notes
This file contains 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
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