1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

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

        共 1073字,需瀏覽 3分鐘

         ·

        2020-07-31 18:22

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

        最近在做一個(gè)需求,功能很簡(jiǎn)單,就是開(kāi)發(fā)一個(gè)輕量級(jí)客戶端,將一個(gè)指定文件中的內(nèi)容通過(guò)TCP發(fā)送到服務(wù)器。由于該文件特別大,有可能到達(dá) 100G 的數(shù)量級(jí),因此處理起來(lái)會(huì)比較慢,為了給用戶提供比較友好的展示界面,因此,在其中加入了進(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ō)的,curtotal是一組,表示的就是第三部分動(dòng)態(tài)展示的當(dāng)前完成數(shù)據(jù)和總數(shù)據(jù)。rate就是第一部分不斷變化的進(jìn)度條,它是一個(gè)string類型的字符串。這個(gè)進(jìn)度條顯示工具還提供了一個(gè)叫graph的屬性,有了它,用戶就可以自定義進(jìn)度條顯示的圖案,比如可以把進(jìn)度條中的方塊換成#=、@等你可以想得到的圖案。

        初始化

        為了能夠方便的調(diào)用該進(jìn)度條工具,因此,為該結(jié)構(gòu)提供了兩個(gè)初始化的方法,分別為NewOptionNewOptionWithGraph,第二個(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ù),分別為starttotaltotal不用說(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)榘俜直瓤偸菑?code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">0到100,而我的進(jìn)度條長(zhǎng)度最長(zhǎng)為 50 個(gè)字符,這也就意味著,每增長(zhǎng)2%,進(jìn)度條就要漲一格,因此,這里的步長(zhǎng)為 2。getPercent是一個(gè)根據(jù)curtotal獲取當(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)換成自己的代碼邏輯即可。

        作者:禹鼎侯

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



        推薦閱讀


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


        站長(zhǎng) polarisxu

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

        不限于 Go 技術(shù)

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


        Go語(yǔ)言中文網(wǎng)

        每天為你

        分享 Go 知識(shí)

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


        瀏覽 75
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            白白嫩嫩美女高清毛片免费看 | 原神同人h黄污本子一区二区 | 裸体鞭打屁股xxxx | 日韩欧美国产精品综合嫩V | 天天操夜夜操狠狠操 | 黄片视频在线观看免费 | 天天一区 | 日韩操B视频 | 免费无码成人一区二区视频 | 国偷自产av一区二区三区麻豆 |