Search code examples
gogoroutine

Getting error "expected ';', found 'go'syntax" while trying to run a function in separate goroutine


This is the code that I am trying to write ->

total ,err := go buildRepository.CountBuildScreenshots(buildId, OrgId, userID)
            if err!=nil {
                fmt.Println(err)
            }

Count Build Screenshots return an integer and an error.

My use case is that I have multiple builds for which I want to run this function. This function is computationally expensive and takes 5 seconds for computing for a single build. Hence I wanted to use wait Groups for the same.

for i := 0; i < len(builds); i++ {
            buildId := builds[i].BuildId
            buildRepository := NewBuildRepository(database.GetReadLTMSConn())
            total ,err := go (buildRepository.CountBuildScreenshots(buildId, OrgId, userID))
            if err!=nil {
                fmt.Println(err)
            }
            (builds[i]).TotalScreenshots = total
            
        }

Solution

  • I would wrap your function in a function that doesn't return anything but writes to a channel. Then you can read from that channel an wait for all results.

    I am wrapping the loop in another goroutine to be able to close the channel after all are done writing to it.

    type result struct {
        Count int
        Err   error
    }
    
    func main() {
        // the channel for the results
        c := make(chan result)
        
        // the top level goroutine waits for all
        // spawned goroutines to be done and closes the channel
        go func(c chan result) {
            // waitgroup is used to wait
            wg := &sync.WaitGroup{}
    
           // kick of the long running functions concurrently
           // in they own goroutine
            for i := 0; i < 10; i++ {
                wg.Add(1)
                go func(c chan result) {
                    defer wg.Done()
                    total, err = count()
                    // write the results to the channel
                    c <- result{total, err}
                }(c)
            }
    
            // wait until all are done
            wg.Wait()
            // important, close the channel
            close(c)
        }(c)
        
    
        // range over the results as they are coming in
        // until the channel is closed
        for r := range c {
            if r.Err != nil {
                fmt.Println(r.Err)
            } else {
                fmt.Println(r.Count)
            }
        }
    
    }
    
    // simulate a longer running function
    func count() (int, error) {
        r := rand.Intn(10)
        time.Sleep(time.Duration(r) * time.Second)
        return 1, nil
    }