В итоге, у меня заработало так:
package main
import (
"io"
"fmt"
"log"
"bufio"
"os/exec"
"strconv"
)
func get_err(id string, stderr io.ReadCloser, errs chan<- string) {
defer stderr.Close()
rd_err := bufio.NewReader(stderr)
for {
err_line, _, err := rd_err.ReadLine()
if err != nil {
if err == io.EOF {
fmt.Println("Exit by EOF...")
}
fmt.Println("Error reading stdout:", err)
return
}
errs <- id+" - "+string(err_line)
}
}
func worker(id int, tasks <-chan string, status chan string, errors chan string) {
// выставляем настройки запуска воркера
cmd := exec.Command("perl", "./worker.pl")
stdin, err := cmd.StdinPipe()
if err != nil {
log.Panic(err)
}
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Panic(err)
}
stderr, err := cmd.StderrPipe()
if err != nil {
log.Panic(err)
}
go get_err(strconv.Itoa(id),stderr, errors)
err = cmd.Start()
if err != nil {
log.Panic(err)
}
rd := bufio.NewReader(stdout)
for {
t := <- tasks
task_id := t[0]
task := t[1:len(t)]
stdin.Write([]byte(task))
fmt.Println("STDIN " + strconv.Itoa(id) + " >>> " + " - task " + string(task_id) + " " + task)
line, _, err := rd.ReadLine()
if err != nil {
if err == io.EOF {
fmt.Println("Exit by EOF...")
}
fmt.Println("Error reading stdout:", err)
return
}
status <- strconv.Itoa(id)+" - task "+string(task_id)+" "+string(line)+"\n"
}
err = cmd.Wait()
if err != nil {
log.Panic(err)
}
}
func main() {
test_words := []string{`raz`, `dva`, `tri`,}
tasks := make(chan string)
status := make(chan string)
errors := make(chan string)
go func(){
for {
bad := <- errors
fmt.Println("<<< STDERR ", bad)
}
}()
go func(){
for {
req := <- status
fmt.Println("<<< STDOUT ", req)
}
}()
// запуск воркера
go worker(w, tasks, status, errors)
// приём/передача запросов/ответов
for i := 0; i < len(test_words); i++ {
tasks <- strconv.Itoa(i)+test_words[i]+"\n"
}
}