来自io.ReadCloser的ReadLine

时间:2012-10-25 08:55:22

标签: go

我需要找到一种从io.ReadCloser对象中读取一行的方法,或者找到一种在“end line”符号上拆分字节数组的方法。但是我不知道终点线符号,我找不到它。

我的应用程序执行一个php脚本,需要从脚本中获取实时输出,并在获取它时对其执行“某些操作”。

这是我的一小段代码:

cmd := exec.Command(prog, args)   
/* cmd := exec.Command("ls")*/
out, err := cmd.StdoutPipe()
if err != nil {
  fmt.Println(err)
}
err = cmd.Start()
if err != nil {
  fmt.Println(err)
}

之后我在go例程中监视out缓冲区。我试过两种方法 1)nr, er := out.Read(buf)其中buf是一个字节数组。这里的问题是我需要为每个新线制动阵列
2)我的第二个选择是创建一个新的bufio.reader
r := bufio.NewReader(out)
line,_,e := r.ReadLine()

如果我执行像ls这样的命令,它运行正常,我逐行获取输出,但如果我执行一个PHP脚本,它会立即得到一个文件结束错误并退出(我猜这是因为延迟来自php的输出)

编辑:我的问题是我在go例程中创建了bufio.Reader,而如果我在minikomi建议的StdoutPipe()之后立即执行它,它可以正常工作

2 个答案:

答案 0 :(得分:6)

您可以使用bufio创建一个阅读器,然后阅读直到下一个换行符(注意,单引号表示字符!):

stdout, err := cmd.StdoutPipe()
rd := bufio.NewReader(stdout)
if err := cmd.Start(); err != nil {
    log.Fatal("Buffer Error:", err)
}

for {
    str, err := rd.ReadString('\n')
    if err != nil {
        log.Fatal("Read Error:", err)
        return
    }
    fmt.Println(str)
}

如果你试图在goroutine中读取读者,没有任何东西可以停止脚本,它将会退出。

答案 1 :(得分:0)

另一个选项是bufio.NewScanner

package main

import (
   "bufio"
   "os/exec"
)

func main() {
   cmd := exec.Command("go", "env")
   out, err := cmd.StdoutPipe()
   if err != nil {
      panic(err)
   }
   buf := bufio.NewScanner(out)
   cmd.Start()
   defer cmd.Wait()
   for buf.Scan() {
      println(buf.Text())
   }
}

https://golang.org/pkg/bufio#NewScanner