英文:
os.Pipe not working as expected with log package
问题
我有一段代码,用于设置os.Pipe
来捕获标准输出和标准错误:
https://github.com/sevagh/stdcap/blob/master/stdcap.go
// Capture执行f()并返回捕获的数据
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
?
英文:
I have a piece of code which sets up an os.Pipe
to capture 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
}
Today I tried using this code with the log
package and it doesn't work.
This works:
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)
}
}
These don't work:
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)
}
}
Any ideas on where I can debug this? Does the Golang log
package not use os.Stdout/os.Stderr
?
答案1
得分: 3
日志记录包在初始化时使用os.Stderr
的值初始化标准记录器。对os.Stderr
变量的修改不会改变记录器字段中的值。
调用log.SetOutput
来从你的捕获函数更改标准记录器的输出位置。不幸的是,没有办法获取标准记录器的输出,以便在捕获函数中保存和恢复它。
英文:
The logging package 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.
Call log.SetOutput to change the output location for the standard logger from your capture function. Unfortunately, there's not a way to get standard logger's output so you can save and restore it in your capture function.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论