1 回答
TA贡献1796条经验 获得超4个赞
Waitgroup 在此代码中是多余的。执行与等待通道结果的循环完美同步。在所有功能完成工作并从通道读取发布的结果之前,代码不会向前移动。仅当您的函数需要在结果发布到通道后执行任何工作时才需要 Waitgroup。
我也更喜欢稍微不同的实现。在发布的实现中,我们不会在每次执行函数时将结果和错误都发送到通道中。相反,我们可以只发送成功执行的结果,并在代码失败时只发送错误。
优点是简化了结果/错误处理。我们在没有nils.
在这个例子中,函数返回一个数字,我们发送它的默认值0以防出错。如果零可能是合法的函数执行结果,则从成功中过滤出不成功的执行结果可能会很复杂。
与错误相同。要检查我们是否有任何错误,我们可以使用像if len(errs) != 0.
package main
import (
"fmt"
)
func processBatch(num int, errChan chan<- error, resultChan chan<- int) {
if num == 3 {
// no need to send result when it is meanenless
// resultChan <- 0
errChan <- fmt.Errorf("goroutine %d's error returned", num)
} else {
square := num * num
resultChan <- square
// no need to send errror when it is nil
// errChan <- nil
}
}
func main() {
batches := [5]int{1, 2, 3, 4, 5}
resultChan := make(chan int)
errChan := make(chan error)
for i := range batches {
go processBatch(batches[i], errChan, resultChan)
}
// use slices instead of arrays because legth varry now
var results []int
var errs []error
// every time function executes it sends singe piece of data to one of two channels
for range batches {
select {
case res := <-resultChan:
results = append(results, res)
case err := <-errChan:
errs = append(errs, err)
}
}
close(resultChan)
close(errChan)
fmt.Println(results)
fmt.Println(errs)
}
https://go.dev/play/p/SYmfl8iGxgD
[25 1 16 4]
[goroutine 3's error returned]
如果你可以使用外部包,我们可以从一些multierr包中获益。例如,github.com/hashicorp/go-multierror。
- 1 回答
- 0 关注
- 161 浏览
添加回答
举报
