最近在做一個(gè)需求,功能很簡(jiǎn)單,就是開(kāi)發(fā)一個(gè)輕量級(jí)客戶(hù)端,將一個(gè)指定文件中的內(nèi)容通過(guò) TCP
發(fā)送到服務(wù)器。由于該文件特別大,有可能到達(dá)100G的數(shù)量級(jí),因此處理起來(lái)會(huì)比較慢,為了給用戶(hù)提供比較友好的展示界面,因此,在其中加入了進(jìn)度條顯示功能。
在這里,說(shuō)一下我在實(shí)現(xiàn)該進(jìn)度條功能時(shí)的一些思路。
成果演示
先看一下最終的成品效果展示:
該進(jìn)度條一共分三部分組成,第一部分是主體進(jìn)度條,第二部分是百分比,第三部分是當(dāng)前完成的數(shù)據(jù)和總數(shù)據(jù)的一個(gè)動(dòng)態(tài)展示。
源碼分析
由于是要在終端上打印出進(jìn)度條的效果,因此,主要還是利用 fmt.Printf
函數(shù)中的 \r
格式控制符。有了這個(gè)基礎(chǔ),我們就可以先設(shè)計(jì)一下結(jié)構(gòu),如下所示:
type Bar struct {
percent int64 //百分比
cur int64 //當(dāng)前進(jìn)度位置
total int64 //總進(jìn)度
rate string //進(jìn)度條
graph string //顯示符號(hào)
}
其中,百分比沒(méi)什么說(shuō)的, cur
和 total
是一組,表示的就是第三部分動(dòng)態(tài)展示的當(dāng)前完成數(shù)據(jù)和總數(shù)據(jù)。 rate
就是第一部分不斷變化的進(jìn)度條,它是一個(gè) string
類(lèi)型的字符串。
這個(gè)進(jìn)度條顯示工具還提供了一個(gè)叫 graph
的屬性,有了它,用戶(hù)就可以自定義進(jìn)度條顯示的圖案,比如可以把進(jìn)度條中的方塊換成 #
、 =
、 @
等你可以想得到的圖案。
初始化
為了能夠方便的調(diào)用該進(jìn)度條工具,因此,為該結(jié)構(gòu)提供了兩個(gè)初始化的方法,分別為 NewOption
和 NewOptionWithGraph
,第二個(gè)初始化的方法即可以自己指定顯示圖案。
NewOption
使用的是默認(rèn)的顯示圖案,也就是上圖展示的方框。其實(shí)現(xiàn)代碼如下所示:
func (bar *Bar) NewOption(start, total int64) {
bar.cur = start
bar.total = total
if bar.graph == "" {
bar.graph = "█"
}
bar.percent = bar.getPercent()
for i := 0; i int(bar.percent); i += 2 {
bar.rate += bar.graph //初始化進(jìn)度條位置
}
}
該函數(shù)提供了兩個(gè)參數(shù),分別為 start
和 total
, total
不用說(shuō),它代表的是總的任務(wù)量,還提供了一個(gè) start
參數(shù),說(shuō)明可以不從 0
開(kāi)始,這也就意味著, 如果你的程序要支持?jǐn)帱c(diǎn)續(xù)傳功能,這個(gè)進(jìn)度條工具依然可以完美支持,只需要將 start
值設(shè)置在斷點(diǎn)處即可。當(dāng)然了,如果你不需要斷點(diǎn)續(xù)傳,每次都從 0
開(kāi)始,只需要將 start
值設(shè)置為0即可。
如果你注意到我在初始化進(jìn)度條位置的時(shí)候,我使用了 i += 2
的步長(zhǎng),這就是我接下來(lái)要說(shuō)的。因?yàn)榘俜直瓤偸菑?0
到 100
,而我的進(jìn)度條長(zhǎng)度最長(zhǎng)為50個(gè)字符,這也就意味著,每增長(zhǎng) 2%
,進(jìn)度條就要漲一格,因此,這里的步長(zhǎng)為2。
getPercent
是一個(gè)根據(jù) cur
和 total
獲取當(dāng)前進(jìn)度完成百分比的一個(gè)函數(shù),其實(shí)現(xiàn)比較簡(jiǎn)單:
func (bar *Bar) getPercent() int64 {
return int64(float32(bar.cur) / float32(bar.total) * 100)
}
第二個(gè)初始化函數(shù)就比較容易實(shí)現(xiàn)了,只需要把 graph
重新覆蓋之后,直接調(diào)用上面的初始化函數(shù)即可。
func (bar *Bar) NewOptionWithGraph(start, total int64, graph string) {
bar.graph = graph
bar.NewOption(start, total)
}
進(jìn)度條展示
那么,如何實(shí)現(xiàn)顯示功能呢?
一般調(diào)用顯示進(jìn)度條時(shí),都是放在循環(huán)中執(zhí)行的,因此,我們只需要在循環(huán)中能夠展示出每輪循環(huán)當(dāng)前的進(jìn)度狀態(tài)即可。
func (bar *Bar) Play(cur int64) {
bar.cur = cur
last := bar.percent
bar.percent = bar.getPercent()
if bar.percent != last bar.percent%2 == 0 {
bar.rate += bar.graph
}
fmt.Printf("\r[%-50s]%3d%% %8d/%d", bar.rate, bar.percent, bar.cur, bar.total)
}
這段代碼中,最重要的就是最后的使用 fmt.Printf
打印的那一句,通過(guò) \r
控制打印效果。
當(dāng)然了,在構(gòu)建 rate
進(jìn)度條時(shí),我需要保存上一次完成的百分比,只有當(dāng)百分比發(fā)生了變化,且步長(zhǎng)變化了 2
時(shí),才需要改變進(jìn)度條的長(zhǎng)度。如果你的屏幕足夠大,你也可以讓你的進(jìn)度條長(zhǎng)度為 100
個(gè)字符,這樣,你就不需要控制進(jìn)度條的步長(zhǎng)為2了,每增長(zhǎng) 1%
,進(jìn)度條前進(jìn)1格,也是沒(méi)有問(wèn)題的。
結(jié)束
由于上面的打印沒(méi)有打印換行符,因此,在進(jìn)度全部結(jié)束之后(也就是跳出循環(huán)之外時(shí)),需要打印一個(gè)換行符,因此,封裝了一個(gè) Finish
函數(shù),該函數(shù)純粹的打印一個(gè)換行,表示進(jìn)度條已經(jīng)完成。
func (bar *Bar) Finish(){
fmt.Println()
}
如何調(diào)用
調(diào)用該進(jìn)度條功能,首先,肯定要構(gòu)建一個(gè) Bar
對(duì)象,使用該對(duì)象進(jìn)行初始化后,即可完成進(jìn)度條的調(diào)用了,一個(gè)完整的調(diào)用程序如下所示:
func main(){
var bar progressbar.Bar
bar.NewOption(0, 100)
for i:= 0; i=100; i++{
time.Sleep(100*time.Millisecond)
bar.Play(int64(i))
}
bar.Finish()
}
以上是一個(gè)最簡(jiǎn)單的調(diào)用,其運(yùn)行效果如下所示:
當(dāng)然了,你也可以使用另一個(gè)初始化函數(shù)指定顯示的圖標(biāo),如下所示:
bar.NewOptionWithGraph(0, 100, "#")
展示效果則如下所示:
當(dāng)然,實(shí)際使用中,你太可能只利用睡眠,而是需要實(shí)現(xiàn)自己的函數(shù)功能,只需要將 time.Sleep(100*time.Millisecond)
換成自己的代碼邏輯即可。
到此這篇關(guān)于golang 進(jìn)度條功能實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)golang 進(jìn)度條內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- Golang實(shí)現(xiàn)異步上傳文件支持進(jìn)度條查詢(xún)的方法
- 使用golang實(shí)現(xiàn)在屏幕上打印進(jìn)度條的操作