<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          實戰(zhàn)項目:用 Go 實現(xiàn)進(jìn)度條功能

          共 1073字,需瀏覽 3分鐘

           ·

          2020-07-31 18:22

          點擊上方藍(lán)色“Go語言中文網(wǎng)”關(guān)注我們,領(lǐng)全套Go資料,每天學(xué)習(xí)?Go?語言

          最近在做一個需求,功能很簡單,就是開發(fā)一個輕量級客戶端,將一個指定文件中的內(nèi)容通過TCP發(fā)送到服務(wù)器。由于該文件特別大,有可能到達(dá) 100G 的數(shù)量級,因此處理起來會比較慢,為了給用戶提供比較友好的展示界面,因此,在其中加入了進(jìn)度條顯示功能。

          在這里,說一下我在實現(xiàn)該進(jìn)度條功能時的一些思路。

          成果演示

          先看一下最終的成品效果展示:

          該進(jìn)度條一共分三部分組成,第一部分是主體進(jìn)度條,第二部分是百分比,第三部分是當(dāng)前完成的數(shù)據(jù)和總數(shù)據(jù)的一個動態(tài)展示。

          源碼分析

          由于是要在終端上打印出進(jìn)度條的效果,因此,主要還是利用fmt.Printf函數(shù)中的\r格式控制符。有了這個基礎(chǔ),我們就可以先設(shè)計一下結(jié)構(gòu),如下所示:

          type?Bar?struct?{
          ????percent?int64??//百分比
          ????cur?????int64??//當(dāng)前進(jìn)度位置
          ????total???int64??//總進(jìn)度
          ????rate????string?//進(jìn)度條
          ????graph???string?//顯示符號
          }

          其中,百分比沒什么說的,curtotal是一組,表示的就是第三部分動態(tài)展示的當(dāng)前完成數(shù)據(jù)和總數(shù)據(jù)。rate就是第一部分不斷變化的進(jìn)度條,它是一個string類型的字符串。這個進(jìn)度條顯示工具還提供了一個叫graph的屬性,有了它,用戶就可以自定義進(jìn)度條顯示的圖案,比如可以把進(jìn)度條中的方塊換成#=@等你可以想得到的圖案。

          初始化

          為了能夠方便的調(diào)用該進(jìn)度條工具,因此,為該結(jié)構(gòu)提供了兩個初始化的方法,分別為NewOptionNewOptionWithGraph,第二個初始化的方法即可以自己指定顯示圖案。

          NewOption使用的是默認(rèn)的顯示圖案,也就是上圖展示的方框。其實現(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ù)提供了兩個參數(shù),分別為starttotaltotal不用說,它代表的是總的任務(wù)量,還提供了一個start參數(shù),說明可以不從0開始,這也就意味著, 如果你的程序要支持?jǐn)帱c續(xù)傳功能,這個進(jìn)度條工具依然可以完美支持,只需要將start值設(shè)置在斷點處即可。當(dāng)然了,如果你不需要斷點續(xù)傳,每次都從0開始,只需要將start值設(shè)置為 0 即可。如果你注意到我在初始化進(jìn)度條位置的時候,我使用了i += 2的步長,這就是我接下來要說的。因為百分比總是從0100,而我的進(jìn)度條長度最長為 50 個字符,這也就意味著,每增長2%,進(jìn)度條就要漲一格,因此,這里的步長為 2。getPercent是一個根據(jù)curtotal獲取當(dāng)前進(jìn)度完成百分比的一個函數(shù),其實現(xiàn)比較簡單:

          func?(bar?*Bar)?getPercent()?int64?{
          ????return?int64(float32(bar.cur)?/?float32(bar.total)?*?100)
          }

          第二個初始化函數(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)度條展示

          那么,如何實現(xiàn)顯示功能呢?一般調(diào)用顯示進(jìn)度條時,都是放在循環(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打印的那一句,通過\r控制打印效果。

          當(dāng)然了,在構(gòu)建rate進(jìn)度條時,我需要保存上一次完成的百分比,只有當(dāng)百分比發(fā)生了變化,且步長變化了2時,才需要改變進(jìn)度條的長度。如果你的屏幕足夠大,你也可以讓你的進(jìn)度條長度為100個字符,這樣,你就不需要控制進(jìn)度條的步長為 2 了,每增長1%,進(jìn)度條前進(jìn) 1 格,也是沒有問題的。

          結(jié)束

          由于上面的打印沒有打印換行符,因此,在進(jìn)度全部結(jié)束之后(也就是跳出循環(huán)之外時),需要打印一個換行符,因此,封裝了一個Finish函數(shù),該函數(shù)純粹的打印一個換行,表示進(jìn)度條已經(jīng)完成。

          func?(bar?*Bar)?Finish(){
          ????fmt.Println()
          }

          如何調(diào)用

          調(diào)用該進(jìn)度條功能,首先,肯定要構(gòu)建一個Bar對象,使用該對象進(jìn)行初始化后,即可完成進(jìn)度條的調(diào)用了,一個完整的調(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()
          }

          以上是一個最簡單的調(diào)用,其運(yùn)行效果如下所示:當(dāng)然了,你也可以使用另一個初始化函數(shù)指定顯示的圖標(biāo),如下所示:

          bar.NewOptionWithGraph(0,?100,?"#")

          展示效果則如下所示:

          當(dāng)然,實際使用中,你太可能只利用睡眠,而是需要實現(xiàn)自己的函數(shù)功能,只需要將time.Sleep(100*time.Millisecond)換成自己的代碼邏輯即可。

          作者:禹鼎侯

          鏈接:https://segmentfault.com/a/1190000023375330



          推薦閱讀


          學(xué)習(xí)交流 Go 語言,掃碼回復(fù)「進(jìn)群」即可


          站長 polarisxu

          自己的原創(chuàng)文章

          不限于 Go 技術(shù)

          職場和創(chuàng)業(yè)經(jīng)驗


          Go語言中文網(wǎng)

          每天為你

          分享 Go 知識

          Go愛好者值得關(guān)注


          瀏覽 75
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  99视频+国产日韩欧美 | 偷拍青娱乐| AV天堂观看 | 啪啪免费网站 | 天天AV天天爽 |