尝试 运行 单独 goroutine 中的函数时出现错误 "expected ';', found 'go'syntax"

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

这是我正在尝试编写的代码 ->

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

计数构建屏幕截图return一个整数和一个错误。

我的用例是我有多个构建,我想要 运行 此功能。该函数计算量大,单次构建需要 5 秒的计算时间。因此我想使用等待组。

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
            
        }

我会将您的函数包装在一个 return 除了写入通道之外什么都不做的函数中。然后您可以从该频道读取并等待所有结果。

我正在将循环包装在另一个 goroutine 中,以便能够在所有写入完成后关闭通道。

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
}

go 关键字启动并发 goroutine。它不等待 goroutine 完成(运行ning concurrently 是 goroutine 的整个 point)因此它无法提供函数的 return 值.

您需要找到一种不同的方式来 returning 您的 goroutine 的结果。您还需要一个同步机制,以便您知道它何时完成。 Achannel是标准解

如果您拥有 CountBuildScreenshots 的实现,您可以直接更改该函数。我假设您不拥有该实现,在这种情况下,我们将 CountBuildScreenshots 包装在另一个函数中以处理响应。我们还将创建一个结构来保存两个 return 值。

type countBuildScreenshotsResult struct {
   total int
   err error
}

现在我们可以创建一个可用于 return 该结构的通道。当我们准备好使用结果时,我们将在通道上等待。

results := make(chan countBuildScreenshotsResult)

现在我们可以调用我们的协程了:

go func() {
   var result countBuildScreenshotsResult
   result.total, result.err := buildRepository.CountBuildScreenshots(buildId, OrgId, userID)
   results <- result
}()

稍后在代码中,我们从通道收集 goroutine 的结果:

res := <-results
if res.err != nil {
   ...
} else {
   ...
}

运行 只有当您在等待 CountBuildScreenshots 到 return 期间还有其他操作要完成时,此函数并发在其自己的 goroutine 中才有意义。如果您将立即等待结果,那么 运行ning 在 goroutine 中对您没有任何作用。只有当你同时有 other 操作 运行 时,goroutines 才有意义。换句话说,如果您最终得到如下代码:

results := make(chan Result)
go func() {
   ...
   results <- result
}()
res := <- results

那么 goroutine 就没有意义了,你也可以 运行 同一个 goroutine 中的操作,因为它无论如何都会在完成时被阻塞。