【发布时间】:2020-08-24 15:10:19
【问题描述】:
我有一个名为 print() 的函数,它每 2 秒打印一次数字,这个函数在 goroutine 中运行。
我需要将它的标准输出打印传递给一个变量并打印它,但不是一次,直到它完成。
我需要有一个无限循环的扫描仪,它将扫描标准输出并打印它,一旦功能完成,扫描仪也会完成。
我尝试使用this answer,但它没有打印任何内容。
这是我试图做的:
package main
import (
"bufio"
"fmt"
"os"
"sync"
"time"
)
func print() {
for i := 0; i < 50; i++ {
time.Sleep(2 * time.Second)
fmt.Printf("hello number: %d\n", i)
}
}
func main() {
old := os.Stdout // keep backup of the real stdout
defer func() { os.Stdout = old }()
r, w, _ := os.Pipe()
os.Stdout = w
go print()
var wg sync.WaitGroup
c := make(chan struct{})
wg.Add(1)
defer wg.Done()
for {
<-c
scanner := bufio.NewScanner(r)
for scanner.Scan() {
m := scanner.Text()
fmt.Println("output: " + m)
}
}
c <- struct{}{}
wg.Wait()
fmt.Println("DONE")
}
我也尝试使用io.Copy 来读取这样的缓冲区,但它也不起作用:
package main
import (
"bytes"
"fmt"
"io"
"os"
"time"
)
func print() {
for i := 0; i < 50; i++ {
time.Sleep(2 * time.Second)
fmt.Printf("hello number: %d\n", i)
}
}
// https://blog.kowalczyk.info/article/wOYk/advanced-command-execution-in-go-with-osexec.html
func main() {
old := os.Stdout // keep backup of the real stdout
defer func() { os.Stdout = old }()
r, w, _ := os.Pipe()
os.Stdout = w
go print()
fmt.Println("DONE 1")
outC := make(chan string)
for {
var buf bytes.Buffer
io.Copy(&buf, r)
outC <- buf.String()
out := <-outC
fmt.Println("output: " + out)
}
// back to normal state
w.Close()
fmt.Println("DONE")
}
【问题讨论】:
-
我不知道您要做什么,但是将 os.Stdout 分配给其他东西是错误的。如果您想在标准输出以外的地方打印,请使用Fprintln 而不是 Println。
-
您的第一个 sn-p 几乎没有致命问题。例如。您尝试使用
Pipe和Scanner捕获fmt.Printf- 这可能会起作用,但随后您将捕获的结果发送到fmt.Println(),它也会打印到Stdout,并且Stdout 已经重定向到Pipe(),所以结果不会打印到控制台(如您所料),而是再次打印到Scanner。还有其他问题,但应该先解决这个问题。 -
@maxim_ge 我把
fmt.Println改成了fmt.Printf,还是不行。我试图将fmt.Printf更改为fmt.Println,但它也不起作用:( -
@Peter 我将
fmt.Println更改为fmt.Fprintf(w, "output: " + m),但它仍然没有打印任何内容。但是我需要从管道的标准输出中读取它,这就是问题所在。基本上我要做的是在函数仍在进行时读取函数的打印。 -
@E235 我会像这样重构你的代码play.golang.org/p/MfAGaC52o_P
标签: go pipe output stdout goroutine