Неблокирующий способ чтения из трубы - PullRequest
0 голосов
/ 08 июня 2019

Я хочу создать простое приложение, которое будет непрерывно считывать вывод из одного приложения, обрабатывать его и записывать обработанный вывод в стандартный вывод. Это приложение может производить много данных в течение секунды, а затем молчит в течение нескольких минут.

Проблема в том, что алгоритм обработки моих данных довольно медленный, поэтому основной цикл блокируется. Когда цикл заблокирован, я теряю данные, которые приходят и в этот момент.

    cmd := exec.Command("someapp")
    stdoutPipe, _ := cmd.StdoutPipe()
    stdoutReader := bufio.NewReader(stdoutPipe)

    go func() {
        bufioReader := bufio.NewReader(stdoutReader)
        for {
            output, _, err := bufioReader.ReadLine()
            if err != nil || err == io.EOF {
                break
            }

            processedOutput := dataProcessor(output);

            fmt.Print(processedOutput)
        }
    }()

Вероятно, лучший способ решить эту проблему - это буферизовать весь вывод и обработать его в другом Goroutine, но я не уверен, как реализовать это в Golang. Какой самый идиоматический способ решить эту проблему?

1 Ответ

0 голосов
/ 10 июня 2019

У вас может быть две программы, один из которых является поставщиком, а другой - потребителем. поставщик выполняет команду и передает данные по каналу потребителю.

    cmd := exec.Command("someapp")
    stdoutPipe, _ := cmd.StdoutPipe()
    stdoutReader := bufio.NewReader(stdoutPipe)
    Datas := make(chan Data, 100)
    go dataProcessor(Datas)
        bufioReader := bufio.NewReader(stdoutReader)
        for {
            output, _, err := bufioReader.ReadLine()
            var tempData Data
            tempData.Out = output
            if err != nil || err == io.EOF {
                break
            }
            Datas <- tempData
            }
    }

и затем вы получите доступ к данным в функции dataProcessor:

func dataProcessor(Datas <-chan Data)  {
    for  {
        select {
        case data := <-Datas:
        fmt.Println(data)
        default:
            continue
        }
    }
}

очевидно, что это очень простой пример, и вы должны настроить его и сделать его лучше. поиск о шанле и горутинах. чтение этого руководства может быть полезным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...