**EDIT to be more concise and clear
I'm fairly new to Go and absolutely new to GoRoutines, but I need to add a level of concurrency to my program I'm building.
What I'm looking to do with this is have both go func
running concurrently, and they are, technically. They aren't running how I would expect them too however.
The top go func
should run every five seconds looking for a new job and an open device to run the job on. If there are new jobs it checks for open devices. Assuming there are three new jobs and two open devices the for _, device := range
loop should run twice assigning each job to a device. Five seconds later the loop would run again and see there is one job left to be run, and check if those devices are open to run the job.
Meanwhile I'd expect the subSSH function to be continuously called.
What's actually happening is that the device loop only runs once every five seconds, so it only takes the first device and runs the code, then it waits five seconds and does the same thing with the second job, then the third job, never utilizing the second device or running that loop twice.
go func() {
for {
duration := 5 * time.Second
for x := range time.Tick(duration) {//this loop runs every five seconds
newJobs := checkForNew(jobcoll)
if len(newJobs) != 0 {
openPool := checkPoolDeviceStatus(poolcoll)
for _, device := range openDevices {
//for each open device this loop should run once
}
}
}
}
}()
go func() {
subSSH(subChannel, jobcoll, poolcoll)
}()
I've attempted adding wait groups in and adding a new wait for the number of new jobs, but this caused the device loop to never execute at all.
I think I'm missing something obvious here, and any assitance is much appreciated! Thanks!
You're on the right path with the ticker, but you have the variables in the wrong scopes. You also have a nested for loop, so go ahead and remove that.
You'll want something like this:
go func() {
ticker := time.NewTicker(5 * time.Second) // setup outside the loop.
for t := range ticker.C { // every time 5 seconds passes, this channel will fire.
newJobs := checkForNew(jobcoll)
if len(newJobs) != 0 {
openPool := checkPoolDeviceStatus(poolcoll)
for _, device := range openDevices {
// the thing should occur.
}
}
}
}()
That should do the trick. See: https://play.golang.org/p/zj6jdoduCcp
If you want a continuously executing goroutine, you'd want a continuous loop.
// only executes once and quits.
go func() { doTheThing() }()
// executes continuously after each execution exit.
go func() { for { doTheThing() } }()
// "background" function
go func() { doTheThingThatNeverExits() }()
A goroutine is designed to be a background process (oversimplication). A goroutine is just an ease-of-use wrapper for easy concurrency when calling functions.
Edit: Missed the last bit.