Go Tips_ 控制台输出进度条
2018-12-22
张子阳
分类: Go 语言
有时候经常会有一些很小的需求,做一些工具应用,比如抓取网页、下载更新数据包等。对于耗时比较久的任务而言,最好是有一个进度显示,可以实时显示进度。下面的代码实现了这一功能,其主要的思想是通过“\r”符号,将光标挪至行首,然后进行输出,此时的输出就覆盖了之前的输出,从而实现实时动画的效果。
这个范例仅仅是一个demo,它还有严重的不足:它是单线程,并只刷新了一行的数据。而诸如下载或者抓取网页,通常都是多线程运行,那么就需要同时更新多行的进度条。此时,就不仅需要将光标挪至行首,还要挪到上一行或者前几行。这种操作的实现思想和这里是类似的,但是使用的特殊符号不同,不再是“\r”。具体可以参考这里:https://en.wikipedia.org/wiki/ANSI_escape_code。
除了控制光标位置以外,还可以控制输出的颜色。但大多数时候,因为时间紧张的关系,在控制台的输出上都非常简单,当需要复杂的输出,就直接写log日志了。
package main
import (
"fmt"
"math/rand"
"strings"
"time"
)
func main() {
testProgress()
}
// 测试进度条
func testProgress() {
// 更新当前的状态
fmt.Println("Start processing... ")
var total = 30
for i := 0; i < total; i++ {
time.Sleep(time.Duration(rand.Intn(400)) * time.Millisecond)
// 计算百分比
percent := int(float32(i+1) * 100.0 / float32(total))
pro := Progress(percent)
pro.Show()
}
fmt.Printf("\nDone!\n")
}
// Progress 进度
type Progress int
// Show 显示进度
func (x Progress) Show() {
percent := int(x)
// fmt.Println("percent: ", percent)
total := 50 // 这个total是格子数
middle := int(percent * total / 100.0)
// fmt.Printf("middle:%d\n", middle)
arr := make([]string, total)
for j := 0; j < total; j++ {
if j < middle-1 {
arr[j] = "-"
} else if j == middle-1 {
arr[j] = ">"
} else {
arr[j] = " "
}
}
bar := fmt.Sprintf("[%s]", strings.Join(arr, ""))
fmt.Printf("\r%s %%%d", bar, percent)
}
输出如下,这里是动态的:
# go run main.go Start processing... [----------------------------------------> ] %83
感谢阅读,希望这篇文章能给你带来帮助!