登录
首页 >  Golang >  Go问答

如何等待特定行打印到 os.Stderr?

来源:stackoverflow

时间:2024-04-12 19:48:35 410浏览 收藏

本篇文章向大家介绍《如何等待特定行打印到 os.Stderr?》,主要包括,具有一定的参考价值,需要的朋友可以参考一下。

问题内容

我正在运行一个 goroutine,它在延迟一段时间后将特定行记录到 os.stderr。我想等到该行被记录为止。到目前为止,我尝试过的是

package main

import (
    "bufio"
    "log"
    "os"
    "strings"
    "time"
)

func main() {
    go func() {
        time.sleep(time.second)
        log.println("hello, world!")
    }()

    scanner := bufio.newscanner(os.stderr)
    for scanner.scan() {
        if strings.contains(scanner.text(), "hello, world!") {
            break
        }
    }
}

但是,如果我运行它,它只会阻塞:

> go run main.go
2022/04/17 00:31:43 Hello, world!

此扫描器是否应该捕获标准错误输出并命中 break 语句?


正确答案


如果你想拦截输出,你可以使用管道,如下所示:

r, w, _ := os.pipe()

log.setoutput(w)

go func() {
    time.sleep(time.second)
    log.println("hello, world!")
}()

scanner := bufio.newscanner(r)

https://go.dev/play/p/HdEs5tbDYDE

似乎如果io.readeros.stderrscanner.scan()无限期地阻塞,而如果我将其设置为像*bytes.buffer这样的自定义读取器,它在 goroutine 有机会写入之前立即返回。

由于此逻辑的上下文是单元测试,因此我使用 assert.Eventually 解决了这个问题:

func testscan(t *testing.t) {
    buf := bytes.newbuffer([]byte{})
    log.setoutput(buf)

    go func() {
        time.sleep(time.second)
        log.println("hello, world!")
    }()

    assert.eventually(t, func() bool {
        scanner := bufio.newscanner(buf)
        for scanner.scan() {
            if strings.contains(scanner.text(), "hello, world!") {
                return true
            }
        }
        return false
    }, 10*time.second, 100*time.millisecond)
}

此测试按预期在 1.1 秒内通过:

> go test ./... -v
=== RUN   TestScan
--- PASS: TestScan (1.10s)
PASS

(当然,这不是最有效的解决方案,因为它可能每次都会读取整个输出,但它应该可以完成这项工作)。

今天带大家了解了的相关知识,希望对你有所帮助;关于Golang的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>