os.Pipe与日志包没有按预期工作

时间:2017-05-24 16:39:06

标签: logging go stdout stderr

我有一段代码设置os.Pipe来捕获Stdout / Stderr:

extensions

// Capture executes f() and returns the captured data
func (s *stdcap) Capture(f func()) string {
    s.mu.Lock()
    defer s.mu.Unlock()

    var old, r, w *os.File

    if s.out {
        old = os.Stdout
        r, w, _ = os.Pipe()
        os.Stdout = w
    } else {
        old = os.Stderr
        r, w, _ = os.Pipe()
        os.Stderr = w
    }

    f()

    outC := make(chan string)
    defer close(outC)

    go func() {
        var buf bytes.Buffer
        io.Copy(&buf, r)
        outC <- buf.String()
    }()

    w.Close()

    if s.out {
        os.Stdout = old
    } else {
        os.Stderr = old
    }

    return <-outC
}

今天我尝试将此代码与log包一起使用,但它不起作用。

这有效:

func TestOutCapture(t *testing.T) {
    sc := StdoutCapture()
    out := sc.Capture(func() {
        fmt.Printf("Hello world!")
    })

    if out != "Hello world!" {
        t.Errorf("Expected \"Hello world!\", got: %s\n", out)
    }
}

func TestErrCapture(t *testing.T) {
    sc := StderrCapture()
    err := sc.Capture(func() {
        fmt.Fprintf(os.Stderr, "Hello world!")
    })

    if err != "Hello world!" {
        t.Errorf("Expected \"Hello world!\", got: %s\n", err)
    }
}

这些不起作用:

func TestLogOutCapture(t *testing.T) {
    sc := StdoutCapture()

    log.SetOutput(os.Stdout)
    out := sc.Capture(func() {
        log.Printf("Hello world!")
    })

    if out != "Hello world!" {
        t.Errorf("Expected \"Hello world!\", got: %s\n", out)
    }
}

func TestLogErrCapture(t *testing.T) {
    sc := StderrCapture()
    log.SetOutput(os.Stderr)

    err := sc.Capture(func() {
        log.Printf("Hello world!")
    })

    if err != "Hello world!" {
        t.Errorf("Expected \"Hello world!\", got: %s\n", err)
    }
}

关于我可以调试此问题的任何想法? Golang log包不使用os.Stdout/os.Stderr吗?

1 个答案:

答案 0 :(得分:3)

日志记录包initializes the standard logger with the value os.Stderr at initialization time。对变量os.Stderr的修改不会更改logger field中的值。

调用log.SetOutput以从捕获函数更改标准记录器的输出位置。不幸的是,没有办法获得标准记录器的输出,因此您可以在捕获功能中保存和恢复它。