golang 实现一个简单的命令行进度条

由于有时候跑脚本几个小时看不到进度,所以想着写一个简单的命令行的进度条。类似下面这样的

创新互联是专业的确山网站建设公司,确山接单;提供网站设计、做网站,网页设计,网站设计,建网站,PHP网站建设等专业做网站服务;采用PHP框架,可快速的进行确山网站开发网页制作和功能扩展;专业做搜索引擎喜爱的网站,专业的做网站团队,希望更多企业前来合作!

其中的原理主要是\r回车符(将光标移动到行首)。这样的话就可以重新打印一行以覆盖之前的那一行。

func main() {
	for i := 0; i < 10; i++ {
		fmt.Printf("\r####")
	}
}
// 结果:只会打印一行
// ####

首先来看进度条的结构。主要就是current:当前进度,和一共的任务数量total。

type Bar struct {
	mu      sync.Mutex
	graph   string    // 显示符号
	rate    string    // 进度条
	percent int       // 百分比
	current int       // 当前进度位置
	total   int       // 总进度
	start   time.Time // 开始时间
}

初始化

func NewBar(current, total int) *Bar {
	bar := new(Bar)
	bar.current = current
	bar.total = total
	bar.start = time.Now()
	if bar.graph == "" {
		bar.graph = "█"
	}
	bar.percent = bar.getPercent()
	for i := 0; i < bar.percent; i += 2 {
		bar.rate += bar.graph //初始化进度条位置
	}
	return bar
}

func NewBarWithGraph(start, total int, graph string) *Bar {
	bar := NewBar(start, total)
	bar.graph = graph
	return bar
}

计算当前百分比

根据当前的进度和总的进度来计算任务进行的百分比。

func (bar *Bar) getPercent() int {
	return int((float64(bar.current) / float64(bar.total)) * 100)
}

获取当前花费时间

计算当前花费了多少时间 h表示小时,m表示分钟,s表示多少秒。

func (bar *Bar) getTime() (s string) {
	u := time.Now().Sub(bar.start).Seconds()
	h := int(u) / 3600
	m := int(u) % 3600 / 60
	if h > 0 {
		s += strconv.Itoa(h) + "h "
	}
	if h > 0 || m > 0 {
		s += strconv.Itoa(m) + "m "
	}
	s += strconv.Itoa(int(u)%60) + "s"
	return
}

加载进度条

使用fmt.Printf 将光标设置到行首并打印进度条,以覆盖上一个进度条。

func (bar *Bar) load() {
	last := bar.percent
	bar.percent = bar.getPercent()
	if bar.percent != last && bar.percent%2 == 0 {
		bar.rate += bar.graph
	}
	fmt.Printf("\r[%-50s]% 3d%%    %2s   %d/%d", bar.rate, bar.percent, bar.getTime(), bar.current, bar.total)
}

设置进度

设置具体的完成任务数,或者任务数加或者减某个值。

func (bar *Bar) Reset(current int) {
	bar.mu.Lock()
	defer bar.mu.Unlock()
	bar.current = current
	bar.load()

}

func (bar *Bar) Add(i int) {
	bar.mu.Lock()
	defer bar.mu.Unlock()
	bar.current += i
	bar.load()
}

调用示例

func main() {

	b := bar.NewBar(0,1000)
	for i := 0 ;i < 1000; i++ {
		b.Add(1)
		time.Sleep(time.Millisecond*10)
	}

} 

至此以上就是全部的代码,非常简单,只是指在跑一些简单任务的时候能有一个提示。


本文标题:golang 实现一个简单的命令行进度条
分享URL:http://pwwzsj.com/article/dsoisei.html