My questions is how to schedule running independent non-blocking functions every interval N.
My initial approach is to use go channels within a select statement to receive the values in a non-blocking manner and use time.Sleep(N)
in each function to schedule the call.
In the code snippet below, this only for the first run; however, after the first call, it keeps calling computeY()
repeatedly without respecting the time.Sleep()
call.
package main
import (
"fmt"
"time"
)
var (
x string = ""
y string = ""
)
func computeY(c chan string) {
time.Sleep(10 * time.Second)
fmt.Println("I'm in Y")
y = "this is Y value"
c <- y
}
func computeX(c chan string) {
time.Sleep(1 * time.Second)
x = "this is X value"
c <- x
}
func main() {
xC := make(chan string)
yC := make(chan string)
for {
go computeX(xC)
go computeY(yC)
select {
case x := <-xC:
fmt.Println(fmt.Sprintf("X: %v, Y: %v", x, y))
case y := <-yC:
fmt.Println(fmt.Sprintf("X: %v, Y: %v", x, y))
}
}
}
You are calling both computeX
and computeY
every iteration of the loop.
Since computeX
takes 1s, the for
loop iterates once per second and an extra time when yC
gets a value.
This means that you're running go computeY
at t=0s
, t=1s
, t=2s
, etc....
The first one terminates at t=10s
, the second at t=11s
, etc...
If you want to make sure you only schedule one computeX
and computeY
at a time, you need to change your main to something along the lines of:
go computeX(xC)
go computeY(yC)
for {
select {
case x = <-xC:
fmt.Printf("Finished computeX: X: %v, Y: %v\n", x, y)
go computeX(xC)
case y = <-yC:
fmt.Printf("Finished computeY: X: %v, Y: %v\n", x, y)
go computeY(yC)
}
}
A few other things to note about your code:
x
and y
are global and assigned in computeX
and computeY
x
and y
fmt.Println(fmt.Sprintf("..."))
is just fmt.Printf("...\n")
""
, that's the default value