示例代码
获取命令行输出
package main
import (
"os/exec"
)
func main() {
cmd := exec.Command("echo", "hello")
buf, _ := cmd.Output() // 错误处理略
print(string(buf))
}
后台运行
package main
import (
"os/exec"
)
func main() {
cmd := exec.Command("sleep", "100")
cmd.Start()
}
分析
os/exec 包用来调用系统命令,并处理输入输出。
exec.Command() 用于创建一个 exec.cmd 结构体,并将传入的参数保存到结构体中。
结构体创建完成后,可以使用 cmd.Start() 或 cmd.Run() 执行。其中,cmd.Run() 会阻塞当前进程,直到命令执行完成。而 cmd.Start() 会保持程序在后台执行,在需要获取结果时,可以调用 cmd.Wait() 来阻塞以获取结果。
cmd.Run() 的实现代码如下:
func (c *Cmd) Run() error {
if err := c.Start(); err != nil {
return err
}
return c.Wait()
}
cmd.Output() 是一个工具函数,它实际上是对 cmd.Run() 的简单包装,可以自动处理 cmd.Stdout 并返回结果。也就是说,不用关心 cmd.Stdout 的设置,只需创建 cmd 并调用 cmd.Output() 获取执行结果即可。
cmd.Output() 的部分代码如下(有删减):
func (c *Cmd) Output() ([]byte, error) {
var stdout bytes.Buffer
c.Stdout = &stdout
// ...
err := c.Run()
// ...
return stdout.Bytes(), err
}
可见,系统使用了 bytes.Buffer 来临时存放输出结果,并在方法结束时将输出结果返回。bytes.Buffer 实现了 io.Reader 和 io.Writer,此处同样可以看出go语言面向组合的设计思想。