-2

我正在尝试从文件中读取数据并立即将读取的块发送给它,而无需等待其他 goroutine 完成文件读取。我有两个功能

func ReadFile(stream chan []byte, stop chan bool) {
    file.Lock()
    defer file.Unlock()
    dir, _ := os.Getwd()
    file, _ := os.Open(dir + "/someFile.json")
    chunk := make([]byte, 512*4)
    for {
        bytesRead, err := file.Read(chunk)
        if err == io.EOF {
            break
        }
        if err != nil {
            panic(err)
            break
        }
        stream <- chunk[:bytesRead]
    }

    stop <- true
}

第一个负责读取文件并将数据块发送到从另一个函数接收的“流”通道

func SteamFile() {
    stream := make(chan []byte)
    stop := make(chan bool)

    go ReadFile(stream, stop)

L:
    for {
        select {
        case data := <-stream:
            //want to send data chunk by socket here
            fmt.Println(data)
        case <-stop:
            break L
        }
    }
}

第二个函数创建 2 个频道,将它们发送到第一个函数并开始收听频道。问题是有时data := <-stream会丢失。例如,我没有收到文件的第一部分,但收到了所有其他部分。当我使用 -race 标志运行程序时,它表明存在数据竞争,并且两个 goroutine 同时写入和读取通道。说实话,我认为这是使用渠道的正常方式,但现在我发现它带来了更多问题。有人可以帮我解决这个问题吗?

4

1 回答 1

1

当我使用 -race 标志运行程序时,它表明存在数据竞争,并且两个 goroutine 同时写入和读取通道。说实话,我认为这是使用频道的正常方式。

是的,而且你几乎肯定误解了比赛检测器的输出。

您在 ReadFile 中共享切片(因此它是底层数组),因此当在 SteamFile [原文如此] 中读取数据时,ReadFile 中的数据会被覆盖。虽然这不应该触发比赛检测器,但它绝对是一个错误。为每个 Read 调用创建一个新切片:

  func ReadFile(stream chan []byte, stop chan bool) {
      file.Lock()
      defer file.Unlock()
      dir, _ := os.Getwd()
      file, _ := os.Open(dir + "/someFile.json")
-     chunk := make([]byte, 512*4)
      for {
+         chunk := make([]byte, 512*4)
          bytesRead, err := file.Read(chunk)
于 2020-11-24T10:18:41.243 回答