同时扫描stdout和stderr

I'm looking for a way to process both stdout and stderr simultaneously as one stream. For a stdout I can use:

cmd := exec.Command(command, flags...)
var wg sync.WaitGroup

stdout, err := cmd.StdoutPipe()
if err != nil {
    return fmt.Errorf("RunCommand: cmd.StdoutPipe(): %v", err)
}

if err := cmd.Start(); err != nil {
    return fmt.Errorf("RunCommand: cmd.Start(): %v", err)
}

scanner := bufio.NewScanner(stdout)
scanner.Split(ScanLinesR)
wg.Add(1)
go func() {
    for scanner.Scan() {
        text := scanner.Text()
        if strings.TrimSpace(text) != "" {
            DoWhateverYouNeedWithText(text)
        }
    }
    wg.Done()
}()

wg.Wait()

But how I add stderr to the same code?

As above commentors suggested I added 2 more goroutines (one for stderr, one for closing channel).

var wg sync.WaitGroup

stdout, err := cmd.StdoutPipe()
if err != nil {
    return fmt.Errorf("RunCommand: cmd.StdoutPipe(): %v", err)
}
stderr, err := cmd.StderrPipe()
if err != nil {
    return fmt.Errorf("RunCommand: cmd.StderrPipe(): %v", err)
}

if err := cmd.Start(); err != nil {
    return fmt.Errorf("RunCommand: cmd.Start(): %v", err)
}

outch := make(chan string, 10)

scannerStdout := bufio.NewScanner(stdout)
scannerStdout.Split(ScanLinesR)
wg.Add(1)
go func() {
    for scannerStdout.Scan() {
        text := scannerStdout.Text()
        if strings.TrimSpace(text) != "" {
            outch <- text
        }
    }
    wg.Done()
}()
scannerStderr := bufio.NewScanner(stderr)
scannerStderr.Split(ScanLinesR)
wg.Add(1)
go func() {
    for scannerStderr.Scan() {
        text := scannerStderr.Text()
        if strings.TrimSpace(text) != "" {
            outch <- text
        }
    }
    wg.Done()
}()

go func() {
    wg.Wait()
    close(outch)
}()

for t := range outch {
    DoWhateverYouNeedWithText(t)
}
// child.go

func main() {
    fmt.Fprintln(os.Stdout, "Child started.")
    time.Sleep(time.Second * 1)
    fmt.Println("Tick...")
    time.Sleep(time.Second * 1)
    fmt.Println("Tick...")
    time.Sleep(time.Second * 1)
    fmt.Println("Tick...")
    time.Sleep(time.Second * 2)
    fmt.Println("Child ended.")
}
// childerr.go
func main() {
    fmt.Fprintln(os.Stdout, "Child started.")
    time.Sleep(time.Second * 1)
    fmt.Fprintln(os.Stdout, "Tick...")
    time.Sleep(time.Second * 1)
    fmt.Fprintln(os.Stdout, "Tick...")
    time.Sleep(time.Second * 1)
    fmt.Fprintln(os.Stdout, "Tick...")
    time.Sleep(time.Second * 2)
    panic("testing")
    fmt.Fprintln(os.Stdout, "Child ended.")
}
func executeCommand(output chan<- string, err chan<- error, start chan interface{}, cmd *exec.Cmd) {

    defer close(start)

    stdout, e := cmd.StdoutPipe()
    if e != nil {
        log.Println("Error starting Cmd: ", e)
        err <- e
        return
    }

    cmd.Stderr = cmd.Stdout

    <-start

    scanner := bufio.NewScanner(stdout)

    for scanner.Scan() {
        output <- scanner.Text()
    }

}

func run(cmd *exec.Cmd) {

    start := make(chan interface{})
    output := make(chan string)
    errChan := make(chan error)
    defer close(output)
    defer close(errChan)

    go executeCommand(output, errChan, start, cmd)

    start <- nil

    if e := cmd.Start(); e != nil {
        log.Println("Error starting Cmd: ", e)
    }

    for {
        select {
        case b := <-output:
            fmt.Println(b)
        case e := <-errChan:
            fmt.Println("ERR EXECUTING COMMAND->", e)
            return
        case <-start:
            fmt.Println("COMPLETED")
            return
        }
    }
}

Use child or childerr to create sample long running proces(es).