我有一个包含要完成的工作的切片,以及在完成所有操作时将包含结果的切片.以下是我的一般过程的草图:
var results = make([]Result, len(jobs))
wg := sync.WaitGroup{}
for i, job := range jobs {
wg.Add(1)
go func(i int, j job) {
defer wg.Done()
var r Result = doWork(j)
results[i] = r
}(i, job)
}
wg.Wait()
// Use results
Run Code Online (Sandbox Code Playgroud)
它似乎工作,但我没有彻底测试,我不确定它是否安全.一般来说,让多个goroutine写入任何内容都不会让我感觉良好,但在这种情况下,每个goroutine都限制在切片中自己的索引,这是预先分配的.
我想替代方案是通过渠道收集结果,但由于结果顺序很重要,这似乎相当简单.以这种方式写入切片元素是否安全?
我需要从多个 go 例程中获取响应并将它们放入一个数组中。我知道可以为此使用通道,但是我不确定如何确保所有 go 例程都完成了对结果的处理。因此我使用了一个等待组。
代码
func main() {
log.Info("Collecting ints")
var results []int32
for _, broker := range e.BrokersByBrokerID {
wg.Add(1)
go getInt32(&wg)
}
wg.Wait()
log.info("Collected")
}
func getInt32(wg *sync.WaitGroup) (int32, error) {
defer wg.Done()
// Just to show that this method may just return an error and no int32
err := broker.Open(config)
if err != nil && err != sarama.ErrAlreadyConnected {
return 0, fmt.Errorf("Cannot connect to broker '%v': %s", broker.ID(), err)
}
defer broker.Close()
return 1003, nil
} …Run Code Online (Sandbox Code Playgroud) 我有以下代码:
package main
import (
"fmt"
"time"
)
type Response struct {
Data string
Status int
}
func main() {
var rc [10]chan Response
for i := 0; i < 10; i++ {
rc[i] = make(chan Response)
}
var responses []Response
for i := 0; i < 10; i++ {
go func(c chan<- Response, n int) {
c <- GetData(n)
close(c)
}(rc[i], i)
}
for _, resp := range rc {
responses = append(responses, <-resp)
}
for _, item := …Run Code Online (Sandbox Code Playgroud) 我目前正在盯着以下代码的增强版本:
func embarrassing(data []string) []string {
resultChan := make(chan string)
var waitGroup sync.WaitGroup
for _, item := range data {
waitGroup.Add(1)
go func(item string) {
defer waitGroup.Done()
resultChan <- doWork(item)
}(item)
}
go func() {
waitGroup.Wait()
close(resultChan)
}()
var results []string
for result := range resultChan {
results = append(results, result)
}
return results
}
Run Code Online (Sandbox Code Playgroud)
这只是在想我的想法.所有这一切都可以用其他语言表达为
results = parallelMap(data, doWork)
Run Code Online (Sandbox Code Playgroud)
即使在Go中不能轻易做到这一点,是不是还有比上面更好的方法呢?