Go-使用goroutine解析的串行端口输入不打印

I am taking input through the serial port (using an Arduino) and I want to parse the data. Here is what I have so far:

package main

import (
    "log"
    "github.com/tarm/serial"
    "bufio"
    "sync"
    "fmt"
)


func readFirstLine(data []string, wg *sync.WaitGroup){
    defer wg.Done()

    fmt.Printf("This is the sensor data:
%q
%q", data[0], data[1])

}

func readSecondLine(data []string, wg *sync.WaitGroup){
    defer wg.Done()

    fmt.Printf("This is the actuator data:
%q", data[2])
}

func main() {
    usbRead := &serial.Config{Name: "COM5", Baud: 9600, ReadTimeout: 0}
    port, err := serial.OpenPort(usbRead)
    var wg sync.WaitGroup
    wg.Add(2)


    if err != nil {
        log.Fatal(err)
    }
    data := []string{}
    scanner := bufio.NewScanner(port)


    for scanner.Scan() {
        data = append(data, scanner.Text())
    }


    for {

    go readFirstLine(data, &wg)
    go readSecondLine(data, &wg)
    wg.Wait()

    }
}   

The serial port currently prints this (looped):

{"temperature":[27.7],"humidity":[46.9],"sensor":"DHT22"}
{"temperature":[25.41545],"sensor":"LM35DZ"}
{"blink":["true"],"actuator":"arduinoLED"}

I am trying to use goroutines to parse the data, and print this (should be looped as well):

This is the sensor data: 
{"temperature":[27.7],"humidity":[46.9],"sensor":"DHT22"}
{"temperature":[25.41545],"sensor":"LM35DZ"}
This is the actuator data: 
{"blink":["true"],"actuator":"arduinoLED"}

However, I am not getting an output. The program simply isn't printing. I think it has to do with the way I am saving the data. Does anyone know how to fix this? And if it's fixed, whether this use of goroutines is the correct method to achieving what I want?

Thank you so much.

dongshi4078
dongshi4078 您的代码永远不会到达调用readFirstLine和readSecondLine的部分,它被卡在扫描程序循环中……有关程序的替代结构,请参见我的答案,该程序使用通道将数据发送至处理goroutine。
2 年多之前 回复
doutanghuan9595
doutanghuan9595 如果我删除WaitGroup并删除“go”并像正常功能一样使用它们,它仍然无法正常工作。我不认为问题与goroutine有关,我认为这是将数据发送到goroutine进行解析的方式。
2 年多之前 回复
doubaben7394
doubaben7394 您为什么认为它与goroutine有关?如果删除WaitGroup而不是调用readFirstLine和readSecondLine而不创建新的goroutine,在这种情况下是否可以打印?
2 年多之前 回复

1个回答

The obvious problem with your code is invalid use of the waitgroup - you init it with 2 and then wait for it in infinite loop... also, your code never reaches to the part where it calls readFirstLine and readSecondLine, it is stuck in the scanner loop

I think the basic structure youre after would be something like following:

func main() {
    // create channels for data
    sensor := make(chan string)
    actuator := make(chan string)
    // launch goroutines which process the data
    var wg, pg sync.WaitGroup
    pg.Add(2)
    go func() {
       defer pg.Done()
       processSensorData(sensor)
    }()
    go func() {
       defer pg.Done()
       processActuatorData(actuator)
    }()
    // read from the data source
    usbRead := &serial.Config{Name: "COM5", Baud: 9600, ReadTimeout: 0}
    port, err := serial.OpenPort(usbRead)
    if err != nil {
        log.Fatal(err)
    }
    scanner := bufio.NewScanner(port)

    for scanner.Scan() {
        data := scanner.Text()
        wg.Add(1)
        go func(data string) {
           defer wg.Done()
           // figure out data packet type and
           // send it into approprioate channel
           if strings.Contains(data, `"sensor"`) {
              sensor <- data
           } else {
              actuator <- data
           }
        }(data)
    }
    // wait for all data to be sent for processing
    wg.Wait()
    // close the channels so goroutines terminate
    close(sensor)
    close(actuator)
    // wait for all data to be processed
    pg.Wait()
}

And the goroutines which process the data would be like:

func processSensorData(data chan string) {
   for d := range data {
      // do something with data
   }
}
duanbenzan4050
duanbenzan4050 谢谢你的作品! 我知道我对goroutine和渠道还没有足够的了解,但是您的回答很有帮助。 非常感谢 :)
2 年多之前 回复
duanchi6397
duanchi6397 我只是将逻辑从您的原始代码复制粘贴到了您的代码上,而没有给它带来太多的麻烦……您可能会以一行的形式获取数据包,而每次对Scan / Text的调用都会给您一个数据包。 因此,您必须确定其类型并将其发送到正确的频道。 查看更新的答案(另请注意,我添加回的WaitGroup,如果没有它,您的主对象可能会在处理所有数据之前退出。)。
2 年多之前 回复
douchenhui5569
douchenhui5569 谢谢,我不再收到该错误! 但是,数据(您发送到goroutine中的变量)和数据[]字符串的类型不匹配。 我尝试通过以下方法修复它:扫描仪.scan()的数据:= [] string {} {数据= append(data,Scanner.Text())go func(data [] string){sensor <-data [ 0]传感器<-数据[1]执行器<-数据[2]}(数据)}消除了错误,但现在不再打印了...我在这里做错了(很抱歉,这么多问题, 我真的很新)
2 年多之前 回复
dongsong8932
dongsong8932 顺便说一句,在单独的goroutine中处理数据实际上有意义吗? 在我看来,这使事情变得不必要地复杂……我想说的是,只有在每个数据点的处理花费“大量时间”时才使用goroutine,否则“内联”进行。
2 年多之前 回复
dongsu0308
dongsu0308 僵局是因为通道没有缓冲。 我编辑了答案,以便在另一个goroutine中发送至频道-应该可以解决该问题。
2 年多之前 回复
doune1000
doune1000 谢谢您的回答! 这是我目前拥有的:func processSensorData(sensor <-chan byte){for i:= range sensor {fmt.Println(i)}},我将类型从字符串更改为字节(因为data [0:2]是 认为字节?),但我收到错误致命错误:所有goroutine都处于睡眠状态-死锁! goroutine 1 [chan send]:main.main()C:/Users/Documents/sensorRead.go:50 + 0x1bb为什么会这样?
2 年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐