Multi Go-Routine Loop Not Executing as Expected

Issue

**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!

Solution

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.

Answered By – SiennaD.

Answer Checked By – Dawn Plyler (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.