【问题标题】:Broken output from a buffered channel range in a GO routineGO 例程中缓冲通道范围的输出损坏
【发布时间】:2019-05-14 02:51:36
【问题描述】:

为什么像下面这样的 GO 例程在使用缓冲通道时会以随机顺序输出字节序列?

这里是复制错误行为的代码,其中data.csv 是一个简单的 CSV,其中包含 1000 行随机数据(每行大约 100 个字节)加上标题行(总共 1001 行)。

package main

import (
    "bufio"
    "os"
    "time"
)

func main() {

    var channelLength = 10000
    var channel = make(chan []byte, channelLength)

    go func() {
        for c := range channel {
            println(string(c))
        }
    }()

    file, _ := os.Open("./data.csv")
    scanner := bufio.NewScanner(file)

    for scanner.Scan() {
        channel <- scanner.Bytes()
    }

    <-time.After(time.Second * time.Duration(3600))

}

以下是输出的前 6 行,作为我所说的“损坏的输出”的示例:

979,C
tharine,Vero,cveror6@blinklist.com,Female,133.153.12.53
980,Mauriz
a,Ilett,milettr7@theguardian.com,Female,226.123.252.118
981
Sher,De Laci,sdelacir8@nps.gov,Female,137.207.30.217
[...]

另一方面,如果 channelLength = 0,代码运行平稳,因此使用无缓冲通道(前 6 行,再次):

id,first_name,last_name,email,gender,ip_address
1,Hebert,Edgecumbe,hedgecumbe0@apple.com,Male,108.84.217.38
2,Minor,Lakes,mlakes1@marriott.com,Male,231.185.189.39
3,Faye,Spurdens,fspurdens2@oakley.com,Female,80.173.161.81
4,Kris,Proppers,kproppers3@gmpg.org,Male,10.80.182.51
5,Bronnie,Branchet,bbranchet4@squarespace.com,Male,118.117.0.5
[...]

数据是随机生成的。

【问题讨论】:

    标签: go channel goroutine


    【解决方案1】:

    来自buffer.Scanner 文档:

    底层数组可能指向将被后续调用 Scan 覆盖的数据

    您在使用通过通道的切片方面存在数据竞争。您需要复制要发送的数据。在这个例子中,这很容易通过使用string 而不是[]byte 并调用scanner.Text 来完成

    【讨论】:

    • 嗨,JimB,你能解释一下为什么我不能在我的机器上重现这个吗?
    • @SamOrozco:这是一场数据竞赛,因此需要精确的时间来获取损坏的输出。然而,即使输出正确,竞争检测器也会显示问题。
    猜你喜欢
    • 2019-01-07
    • 1970-01-01
    • 2018-10-02
    • 1970-01-01
    • 2021-12-25
    • 1970-01-01
    • 2017-09-06
    • 1970-01-01
    • 2018-04-15
    相关资源
    最近更新 更多