golang里面有对标准输入和输出的操作方式

    Stdin  = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
    Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
    Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")

第一个需要理解的是,os.Stdout是什么? 它是指针,它是golang将自己的输出指向的指针,程序的标准输出会导入到os.Stdout里面,同理os.Stdin也就是标准输入 先看下面这个例子

package main

import (
    "bytes"
    "io"
    "os"
    "fmt"
)

// not thread safe
func captureStdout(f func()) string {
    fmt.Printf("before os.Stdout :%v \n", os.Stdout)
    old := os.Stdout
    r, w, _ := os.Pipe()
    os.Stdout = w
    fmt.Printf("in w :%v \n", w)
    fmt.Printf("in os.Stdout :%v \n", os.Stdout)
    f()

    w.Close()
    os.Stdout = old
    fmt.Printf("after os.Stdout :%v \n", os.Stdout)
    var buf bytes.Buffer
    io.Copy(&buf, r)
    return buf.String()
}

func doSomething() {
    fmt.Println("This goes to STDOUT")
}

func main() {

    // invoke doSomething and return whatever it writes to STDOUT
    message := captureStdout(doSomething)

    fmt.Printf("get function result is :%s \n", message)

}

这是一个截获程序标准输出的例子,先看结果

before os.Stdout :&{0xc42000a140} 
after os.Stdout :&{0xc42000a140} 
get function result is :in w :&{0xc42000a1c0} 
in os.Stdout :&{0xc42000a1c0} 
This goes to STDOUT

这个里面先是os.Stdout = w,将w赋值给标准输出,此时标准输出将不会指向/dev/stdout,所以程序的输出会直接导入的w里面 通过io.Copy(&buf, r)获取pipe数据并发到buf里面,然后返回,这样就可以截获输出了。 那如果我们也使用这个标准的输入输出是否可以呢? 答案是肯定的

package main

import (
    "os/exec"
    "os"
    "io"
)

func main() {
    cmd := exec.Command("ls", "-l")
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    cmd.Stdin = os.Stdin
    cmd.Run()
    //os.Stdout = nil
    io.WriteString(os.Stdout, "Hello World \n")
}

如果只是设置os.Stdout = nil,那么只有io.WriteString(os.Stdout, "Hello World \n")会受到影响

results matching ""

    No results matching ""