os.Pipe 未按预期使用日志包

os.Pipe not working as expected with log package

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

https://github.com/sevagh/stdcap/blob/master/stdcap.go

// 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吗?

日志包initializes the standard logger with the value os.Stderr at initialization time. Modifications to the variable os.Stderr do not change the value in the logger field

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