【问题标题】:Reading from golang channels in order按顺序从 golang 频道中读取
【发布时间】:2017-01-03 14:11:35
【问题描述】:

我正在尝试通过 go 通道实现并行处理和通信。

我基本上试图解决的是并行处理特定数据,并按顺序获得结果 => 为此目的引入了类型Chunk(见下文)。

我只是为每个块处理创建新通道并将它们保存在切片中 => 期望在我之后迭代它们时进行排序。

我的程序的简化版是(https://play.golang.org/p/RVtDGgUVCV):

package main

import (
    "fmt"
)

type Chunk struct {
    from int
    to   int
}

func main() {
    chunks := []Chunk{
        Chunk{
            from: 0,
            to:   2,
        },
        Chunk{
            from: 2,
            to:   4,
        },
    }

    outChannels := [](<-chan struct {
        string
        error
    }){}

    for _, chunk := range chunks {
        outChannels = append(outChannels, processChunk(&chunk))
    }

    for _, outChannel := range outChannels {
        for out := range outChannel {
            if out.error != nil {
                fmt.Printf("[ERROR] %s", out.error)
                return
            }

            fmt.Printf("[STDOUT] %s", out.string)
        }
    }
}

func processChunk(c *Chunk) <-chan struct {
    string
    error
} {

    outChannel := make(chan struct {
        string
        error
    })

    go func() {
        outChannel <- struct {
            string
            error
        }{fmt.Sprintf("from: %d to: %d\n", c.from, c.to), nil}

        close(outChannel)
    }()

    return outChannel
}

我看到的输出是:

[STDOUT] from: 2 to: 4
[STDOUT] from: 2 to: 4

但我希望看到的是:

[STDOUT] from: 0 to: 2
[STDOUT] from: 2 to: 4

我在这里做错了什么?没看到。

【问题讨论】:

    标签: go parallel-processing channel


    【解决方案1】:

    问题在于main 的第一个for 循环。当您使用for range 循环时,循环变量(此处为chunk)会创建一次,并在每次迭代时分配每个切片元素的副本。

    当你调用processChunk(&amp;chunk) 时,你传递的是这个循环变量的地址,这个变量的值随着每次迭代而改变。因此,函数processChunk 总是最终处理chunks 循环中的最后一项,因为这是*chunk 在for 循环完成后指向的内容。

    要修复,请使用切片索引:

    for i := 0; i < len(chunks); i++ {
        // pass chunk objects by indexing chunks
        outChannels = append(outChannels, processChunk(&chunks[i]))
    }
    

    固定代码:https://play.golang.org/p/A1_DtkncY_

    你可以阅读更多关于rangehere的信息。

    【讨论】:

      猜你喜欢
      • 2021-05-17
      • 2019-01-30
      • 2018-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-05
      • 1970-01-01
      • 2019-02-02
      相关资源
      最近更新 更多