arrays - 同时遍历两个集合
问题描述
在 Go 中,同时遍历 2 个集合的最佳方法是什么?
在我的程序中,我有一个创建两个数组的函数,以及另一个需要同时迭代它们的函数(在每次迭代中访问两个数组中的第 i 个元素)。
如果我有一个输入,我会在第一个函数中创建一个通道(而不是一个数组),并使用范围循环从各种 goroutine 对其进行迭代。
在这种情况下,有没有比创建索引通道并使用它来访问数组更简单的解决方案?
func main() {
// Prepare two arrays.
arrA := [12]int{1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144}
arrB := arrA
// Create a channel with the indexes.
c := make(chan int, len(arrA))
for i := range arrA {
c <- i
}
close(c)
poolSize := 3
var wg sync.WaitGroup
wg.Add(poolSize)
for i := 1; i <= poolSize; i++ {
go func() {
defer wg.Done()
for j := range c {
fmt.Printf("%v == %v\n", arrA[j], arrB[j])
}
}()
}
wg.Wait()
}
解决方案
go中有一句话
“不要通过共享内存来交流,通过交流来共享内存”
它基本上归结为;
“不要在 2 个 goroutine 之间共享状态,而是使用通道在例程之间传递所需的值”
它可能是您的简化示例的副产品,但是您为什么不能将arrA
and的范围限制在arrB
单个 goroutine 内,而不是传递索引,这是某种将发送值的生产者或生成器。这些值的接收者可以对它们进行处理,在这种情况下是相等的比较。
type pair struct {
a, b int
}
c := make(chan pair, len(arrA))
for i := range arrA {
c <- pair{a: arrA[i], b: arrB[i]}
}
close(c)
poolSize := 3
var wg sync.WaitGroup
wg.Add(poolSize)
for _ := range poolSize {
go func() {
defer wg.Done()
for p := range c {
fmt.Printf("%v == %v\n", p.a, p.b)
}
}
}
这似乎是一个微不足道的小变化,但好处是:
- 隔离:您将 arrA 和 arrB 的访问器范围限制为单个生产 goroutine,稍后在代码中限制竞争条件/复杂逻辑/错误的范围。
- 重用:您可以重用在代码库中其他地方使用的代码函数,
chan pair
因为它们不直接访问特定数组中的值,而是传递它们需要的所有值。
扩展它;假设您只需要来自索引的值arrB
而不关心索引,那么您应该在通道上发送该值,并删除对pair
类型的需要。
推荐阅读
- python - 如何将 2dp 添加到 Plotly Go Sunburst
- javascript - 使 Django-leaflet 弹出窗口始终打开以显示 django-geojson 功能属性
- docker - 连接过程中出错:获取 http://docker:2375/v1.24/containers/json: dial tcp: lookup docker on 10.0.2.3:53: server misbehaving
- c - 如何有效地在字符串指针的特定位置插入字符?
- ios - 搜索 Tableview 时如何显示子响应?
- r - 使用 ggplot2 或在 R 中绘图创建子弹图
- algorithm - 超出算法时间限制
- python - 如何用多个条件替换列值
- python - 简单 Keras ANN MNIST 数据集中的错误
- discord.js - 用户发送消息时如何添加角色