同时遍历两个集合

AMT:

在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()
}
扎克:

俗话说

“不要通过共享内存进行通信,而是通过通信共享内存”

基本上可以归结为:

“不要在两个goroutine中共享状态,而是使用通道在例程之间传递所需的值”

它可能是简化示例的副产品,但为什么不传递标记,却为什么不限制的范围,arrAarrB将其限制在单个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)
        }
    }
}

这看似微不足道的变化,但好处是:

  1. 隔离:您将访问arrA和arrB的访问器的范围限制为单个生成的goroutine,将争用条件/复杂逻辑/错误的范围限制在代码的后面。
  2. 重用:您可以重用消耗chan pair代码库中其他位置的代码函数,因为它们不直接访问特定数组中的值,而是传递它们所需的所有值。

扩展这个;假设您只需要arrB索引中的值,而不关心索引,则应在通道上发送该值,并消除对pair类型的需要

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章