@Konvergent
начинающий разработчик

Как передавать данные из go в подпроцесс(через exec.Command), но без перезапуска подпроцесса(т.е. постоянно писать/читать)?

Есть такой код:
cfCmd := exec.Command("perl", "./test.pl")
    cfIn, _ := cfCmd.StdinPipe()
    cfOut, _ := cfCmd.StdoutPipe()
    err := cfCmd.Start()
    if err != nil { 
    	fmt.Print(err.Error()) 
    	os.Exit(1) 
    } 
    cfIn.Write([]byte(task))
    cfIn.Close()
    cfBytes, _ := ioutil.ReadAll(cfOut)
    cfCmd.Wait()
    
    res := "\n>>> Server: test.pl " + fmt.Sprint(id) + " вернул: \n" + string(cfBytes)

Но проблема в том, что мне нужно только раз запустить test.pl, а потом писать в него данные и читать ответы.
Как это правильно сделать на golang?
  • Вопрос задан
  • 160 просмотров
Пригласить эксперта
Ответы на вопрос 1
Не закрывайте cfIn, пишите туда данные, а читайте из cfOut, в разных горутинах.

Например, так
package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"os/exec"
	"strings"
)

func main() {
	cfCmd := exec.Command("perl", "test.pl")
	cfIn, err := cfCmd.StdinPipe()
	if err != nil {
		panic(err)
	}
	cfOut, err := cfCmd.StdoutPipe()
	if err != nil {
		panic(err)
	}

	err = cfCmd.Start()
	if err != nil {
		panic(err)
	}

	go ProcessStdin(cfIn)
	ProcessStdout(cfOut)

	err = cfCmd.Wait()
	if err != nil {
		panic(err)
	}
}

func ProcessStdin(stdin io.WriteCloser) {
	defer stdin.Close()
	stdin.Write([]byte("some task"))
	stdin.Write([]byte("some other task"))
	// ......
}

func ProcessStdout(stdout io.ReadCloser) {
	defer stdout.Close()

	rd := bufio.NewReader(stdout)
	for {
		line, err := rd.ReadString('\n')
		if err != nil {
			fmt.Println("Error reading stdout:", err)
			os.Exit(1)
		}
		line = strings.TrimSpace(line)

		fmt.Println("Got line from a process:", line)
	}
}


Не забудьте в перловой программе сделать
$| = 1;
Иначе перл не будет сбрасывать буфер stdout и вы ничего не получите в интерактиве.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы