【问题标题】:golang io.writer new line after finished writing stringgolang io.writer 写完字符串后换行
【发布时间】:2019-11-07 02:42:18
【问题描述】:

我有以下代码使用a package 来绘制进度条

type tmpStruct struct {
}

func (t *tmpStruct) Write(p []byte) (n int, err error) {
    fmt.Fprintf(os.Stdout, "%s", string(p))
    return len(p), nil
}

func demoLoadingBarCount(maximumInt int) {
    buf := tmpStruct{}
    if nBuf, ok := interface{}(&buf).(io.Writer); ok {
        bar := progressbar.NewOptions(
            maximumInt,
            progressbar.OptionSetTheme(progressbar.Theme{Saucer: "█", SaucerPadding: "-", BarStart: ">", BarEnd: "<"}),
            progressbar.OptionSetWidth(100),
            progressbar.OptionSetWriter(nBuf),
        )
        for i := 0; i < maximumInt; i++ {
            bar.Add(1)
            time.Sleep(10 * time.Millisecond)
        }
    }
}

所有作品,除了最后没有新行,你可以在这里看到

我无法在 Write 函数中添加换行符,因为这会在每个字节推送到写入器后导致它换行。有没有一种巧妙的方法可以做到这一点?

编辑: 我希望新行进度条之后和下一行打印出来之前

【问题讨论】:

  • @Volker:我的猜测:对tmpStruct does not implement io.Writer (Write method has pointer receiver)的一个考虑不周的回应
  • 所以你想在状态栏后换行吗?那么,为什么不在状态栏之后打印一个换行符呢?
  • 重复是程序员最擅长的。编写一个函数来为您处理它。我没有发现任何问题。
  • 我投了反对票,因为这个问题很不清楚。我没有看到明确的问题陈述。我看到一个很小的图形,我猜它表明了一个未指明的不正确行为(在 cmets 之后,我认为我理解了意图)。
  • 这也不是真正的最小复制案例。事实上,它的代码比必要的多(考虑到不必要的tmpStruct 类型和不必要的类型断言),同时代码也不够多,因为那里没有完整的可执行示例来演示故障模式。

标签: go newline writer


【解决方案1】:

您所问问题的简单答案是在进度条完成后打印一个额外的换行符:

func demoLoadingBarCount(maximumInt int) {
    buf := &tmpStruct{}
    bar := progressbar.NewOptions(
        maximumInt,
        progressbar.OptionSetTheme(progressbar.Theme{Saucer: "█", SaucerPadding: "-", BarStart: ">", BarEnd: "<"}),
        progressbar.OptionSetWidth(100),
        progressbar.OptionSetWriter(buf),
    )
    for i := 0; i < maximumInt; i++ {
        bar.Add(1)
        time.Sleep(10 * time.Millisecond)
    }
    fmt.Fprintf(buf, "\n") // <---- Add this
}

虽然您的 cmets 表明这是有问题的,但您还没有解释如何。如果您更新您的问题以解释为什么这是一个问题,也许可以找到更好的解决方案。

【讨论】:

  • 是的,这是一个解决方案,并且确实有效。我希望这可以在自定义 io.Writer 的 Write 函数中处理,以便可以传递编写器,而编码器不必知道,或者意识到他们在想要使用时需要这样做进度条。最终,我想传递进度条并在需要时调用它/使用它,而不必每次都担心新行。
  • 如果你切换到io.WriteCloser并且你知道进度条会在编写器完成后关闭,你可以让你的Close()函数写一个最后一个“\n”。但这听起来比仅仅打印一个“\n”更具侵入性。没有神奇的解决方案。
  • 难道不是每次使用进度条都需要自己的实例化吗?因为它正在跟踪不同的状态?我不明白你怎么能把一个人传出去。
  • 这对我的用例可能很有趣。谢谢,我会调查的。顺便说一句,感谢您进行更彻底的讨论。我觉得你的方法是“有代价的帮助”。如果您喜欢,请将其作为反馈。我看到我的问题可以更具描述性。著名的。最终,我计划在我计划传递的 tmpStruct 中包装一个指向 progressBar 的指针(并且我可以重新分配它)和 io.writer。所以是的,一个特定的 PB 不能被重用,但是一个指针可以并且作者可以保持不变。
  • 我认为 &amp;tmpStruct{} 让我感到困惑的是该函数需要一个 io.Writer,而不是 *io.Writer,所以我认为我不应该传递 tmpStruct{} 的地址而不是tmpStruct{}
猜你喜欢
  • 2017-10-23
  • 2016-08-11
  • 1970-01-01
  • 1970-01-01
  • 2016-04-28
  • 1970-01-01
  • 2016-11-13
  • 1970-01-01
  • 2014-02-27
相关资源
最近更新 更多