【问题标题】:Buffered channels in GoGo 中的缓冲通道
【发布时间】:2019-08-14 05:30:25
【问题描述】:

我正在使用 raspberry pi 和 arduino 开发一个项目。我正在树莓派上编写一个 GO 程序,以每秒 115200 波特率从 Arduino 接收 UART 数据。树莓派读取 UART 数据,将其保存到文件(基于 file1file2 等的值),然后将文件发送到 ftp 服务器。

由于上传到服务器可能需要一些时间,具体取决于网络,我想使用 go 并发,以便 UART 读取和保存到文件不会中断。以下是我尝试应用的伪代码(骨架)。我在代码中的想法是文件路径将按顺序缓冲在通道中,并且上传以相同的顺序执行。我做得对吗?有没有更好的方法来解决这个问题?

package main

import "strings"

func SendFile(filePath string) {

}
// based on the value of the data, SaveToFile saves the data to either file1, file2 or file3
func SaveToFile(uartData []string) filePath string {

    return filePath
}

func main() {


    ch := make(chan string, 1000)

    //uartInit initialization goes here
    uart := uartInit()

    //infinite loop for reading UART...
    for {
        buf := 1024 // UART buffer
        data := uart.Read(buf)
        uartData = strings.Split(string(buf), " ")

        //channel receives filepath 
        ch <- SaveToFile(uartData)

        //channel sends filepath
        go SendFile(<-ch)

    }
}

【问题讨论】:

  • 好吧,我不认为这就是你使用频道的方式......你可以试试这个play.golang.org/p/6jDrSPaPrUQ
  • @SivaGuru 您的方法似乎是合理的。我会尽快发布我的解决方案。

标签: go concurrency channels


【解决方案1】:

您正在将一个字符串写入通道,然后将其读回。 sendFile() 在不同的 goroutine 中运行,但您使用它的方式不需要通道。你可以简单地做

 fname:= SaveToFile(uartData)
 go SendFile(fname)

但是,我不认为这是你想要做的。

相反,您应该有一个 goroutine,您可以在其中从 UART 读取数据,并写入缓冲通道。监听该通道是另一个将数据块写入文件的 goroutine。当它准备好发送时,创建第三个 goroutine 来发送文件。

【讨论】:

  • "创建第三个 goroutine 来发送文件。"这根本不能解决问题;行为将与原始代码中的行为完全相同。第二个 goroutine 必须一次上传一个文件以保证顺序。
【解决方案2】:

在阅读了 cmets 和一些在线资源之后,到目前为止,以下方法似乎运行良好。 video 的前 8 分钟对理解这个概念很有帮助。不过,我不确定defer close(ch)

package main

import "strings"

func SendFile(ch chan string) {
  for filePath := range ch {
   //upload file here
  }

}

func SaveToFile(uartData []string) filePath string {

    return filePath
}

func main() {


    ch := make(chan string, 1000)
    defer close(ch)
    go SendFile(<-ch)

    uart := uartInit()


    for {

        data := uart.Read(buf)
        uartData = strings.Split(string(buf), " ")
        ch <- SaveToFile(uartData)

    }
}

【讨论】:

  • 当你在你的频道上移动时,它会像一个无限循环(当它为空时它会阻塞)。defer close(ch) 将确保“SendFile”goroutine 停止。 (play.golang.org/p/og5DnPzlu1I)
  • @SivaGuru 感谢您的回复。那么,在您发送的示例中,defer close(queue)close(queue) 之间有区别吗?我刚刚对其进行了测试,defer close(queue) 在运行时会导致死锁。
  • 那么 defer 确保在函数返回或函数结束时执行命令。在示例中使用 defer 是不好的,因为函数不会返回。 Close(queue) 将立即关闭通道。延迟关闭(queue) 将在函数返回时关闭。由于函数不会返回,它将陷入死锁。在您的示例中,您可以使用 defer
  • @SivaGuru 谢谢你的解释。竖起大拇指!
猜你喜欢
  • 2018-10-02
  • 2021-12-25
  • 1970-01-01
  • 2017-09-06
  • 2019-01-07
  • 2018-04-15
  • 2013-12-17
  • 2018-02-18
  • 2012-10-17
相关资源
最近更新 更多