最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

golang程序進(jìn)度條實(shí)現(xiàn)示例詳解

 更新時(shí)間:2022年08月29日 11:33:16   作者:jonylee  
這篇文章主要為大家介紹了golang程序?qū)崿F(xiàn)進(jìn)度條示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

最近在工作中寫一個(gè)批處理腳本,令人抓狂的是每次都不知道腳本要跑到啥時(shí)候結(jié)束,于是想到給程序添加個(gè)進(jìn)度條。

逛了一圈,沒找到特別趁手的輪子,本著有手就行的原則,今天簡(jiǎn)單地給大家擼一個(gè)終端進(jìn)度條。

原理

終端進(jìn)度條打印的原理是通過輸入\r將光標(biāo)位置移動(dòng)到當(dāng)前行的行首,重新打印一份進(jìn)度信息。

如果是使用\n,則光標(biāo)會(huì)另起一行打印信息。

上才藝

首先從核心功能出發(fā),進(jìn)度條要告訴我的信息有

  • 一共要完成多少任務(wù)
  • 現(xiàn)在完成了多少任務(wù)
  • 到什么時(shí)候才能完成全部任務(wù)

根據(jù)上面的需求

畫了個(gè)大概的樣子長(zhǎng)這樣 [█████████████████████████]100/100 [eta]16:33:39

抽象的用戶調(diào)用函數(shù)有3個(gè)

New()新建進(jìn)度條實(shí)例 Done()推進(jìn)進(jìn)度條進(jìn)展 Finish()完成進(jìn)度條

是不是和sync.WaitGroup很像。

調(diào)用代碼

func main() {
	bar := progress.New(100)
	for i := 0; i < 100; i++ {
		time.Sleep(time.Second / 10)
		bar.Done(1)
	}
	bar.Finish()
}

所以根據(jù)用戶調(diào)用需求,首先定義進(jìn)度條結(jié)構(gòu)體。

type Bar struct {
	total         int64         // 總進(jìn)度
	current       int64         // 當(dāng)前進(jìn)度
	filler        string        // 進(jìn)度填充字符
	filler_length int64         // 進(jìn)度條長(zhǎng)度
	time_format   string        // 進(jìn)度條時(shí)間格式
	interval      time.Duration // 打印時(shí)間間隔
	begin         time.Time     // 任務(wù)開始時(shí)間
}

然后根據(jù)用戶調(diào)用的函數(shù),給出函數(shù)實(shí)現(xiàn),當(dāng)然這里面加了一些函數(shù)參數(shù)可選項(xiàng)。

可以在初始化實(shí)例的時(shí)候自定義一些元素,比如填充字符,比如時(shí)間格式或者是每隔多少時(shí)間刷新一次進(jìn)度條等等。

// New 新建進(jìn)度條實(shí)例
func New(total int64, opts ...func(*Bar)) *Bar {
	bar := &Bar{
		total:         total,
		filler:        "█",
		filler_length: 25,
		time_format:   "15:04:05", // 2006-01-02T15:04:05
		interval:      time.Second,
		begin:         time.Now(),
	}
	for _, opt := range opts {
		opt(bar)
	}
	// 定時(shí)打印
	ticker := time.NewTicker(bar.interval)
	go func() {
		for bar.current < bar.total {
			fmt.Print(bar.get_progress_string())// 打印進(jìn)度
			<-ticker.C
		}
	}()
	return bar
}
// Done 更新完成進(jìn)度
func (bar *Bar) Done(i int64) {
	bar.current += i
}
// Finish 完成最后進(jìn)度條
func (bar *Bar) Finish() {
	fmt.Println(bar.get_progress_string())
}
// WithFiller 設(shè)置進(jìn)度條填充字符
func WithFiller(filler string) func(*Bar) {
	return func(bar *Bar) {
		if len(bar.filler) != 0 {
			bar.filler = filler
		}
	}
}

那么處理完了用戶怎么使用之后,我們就來開始處理怎么給用戶展示進(jìn)度條效果。

要想根據(jù)進(jìn)度填充不同的字符比例,先算進(jìn)度百分比,長(zhǎng)下面這樣子。

//get_percent 獲取進(jìn)度百分比,區(qū)間0-100
func (bar *Bar) get_percent() int64 {
	return bar.current * 100 / bar.total
}

因?yàn)槲覀冞M(jìn)度條并不需要那么精確,所有這里都用的是整數(shù)來處理,更方便一些,不用做各種類型轉(zhuǎn)換。

那么拿到百分比之后,就能根據(jù)進(jìn)度條總長(zhǎng)度來計(jì)算要填充多少個(gè)█。

接下來算任務(wù)什么時(shí)候完成,這里用的算法是,用當(dāng)前完成了多少個(gè)任務(wù)和花了多少時(shí)間來估算總?cè)蝿?wù)數(shù)的要花費(fèi)多少時(shí)間,得到預(yù)計(jì)什么時(shí)候完成,代碼是這樣子的:

//get_eta 獲取eta時(shí)間
func (bar *Bar) get_eta(now time.Time) string {
	eta := (now.Unix() - bar.begin.Unix()) * 100 / (bar.get_percent() + 1)
	return bar.begin.Add(time.Second * time.Duration(eta)).Format(bar.time_format)
}

最后,我們來處理下需要在控制臺(tái)打印的字符串,同時(shí)作為非核心需求,我們還想看批處理操作的速度,所以這里用QPS來表達(dá)我們整個(gè)任務(wù)處理的速度。

QPS表達(dá)任務(wù)處理速度

//get_progress_string 獲取打印控制臺(tái)字符串
func (bar *Bar) get_progress_string() string {
	fills := bar.get_percent() * bar.filler_length / 100
	for i := int64(0); i < bar.filler_length; i++ {
		switch {
		case i < fills:
			chunks[i] = bar.filler
		default:
			chunks[i] = " "
		}
	}
	now := time.Now()
	eta := bar.get_eta(now)
	qps := bar.current / (now.Unix() - bar.begin.Unix() + 1)
	return fmt.Sprintf("\r[%s]%d/%d [eta]%s [qps]%d ", strings.Join(chunks, ""), bar.current, bar.total, eta, qps)
}

最終呈現(xiàn)的效果 [█████████████████████████]100/100 [eta]16:33:39 [qps]9 

當(dāng)然,為了更酷炫一點(diǎn),同時(shí)還引入了emoji字符,能夠根據(jù)字符自適應(yīng)地調(diào)整顯示效果。

下面是項(xiàng)目github地址,供大家參考

https://github.com/jony-lee/go-progress-ba

知識(shí)點(diǎn)總結(jié)

下面是知識(shí)點(diǎn)總結(jié)

  • 使用\r來將控制臺(tái)光標(biāo)定位到行首實(shí)現(xiàn)行內(nèi)進(jìn)度條刷新。
  • 使用函數(shù)可選參數(shù)來實(shí)現(xiàn)用戶自定義設(shè)置。
  • 使用函數(shù)time.NewTicker()實(shí)現(xiàn)定時(shí)刷新控制臺(tái)進(jìn)度條。

以上就是golang程序進(jìn)度條實(shí)現(xiàn)示例詳解的詳細(xì)內(nèi)容,更多關(guān)于golang程序進(jìn)度條的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Golang實(shí)現(xiàn)KV存儲(chǔ)引擎實(shí)例探究

    Golang實(shí)現(xiàn)KV存儲(chǔ)引擎實(shí)例探究

    這篇文章主要為大家介紹了Golang實(shí)現(xiàn)KV存儲(chǔ)引擎實(shí)例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • 淺析如何利用Go的plugin機(jī)制實(shí)現(xiàn)熱更新

    淺析如何利用Go的plugin機(jī)制實(shí)現(xiàn)熱更新

    熱更新,或稱熱重載或動(dòng)態(tài)更新,是一種軟件更新技術(shù),允許程序在運(yùn)行時(shí),不停機(jī)更新代碼或資源,本文主要來討論下GO語言是否可以利用plugin機(jī)制實(shí)現(xiàn)熱更新,感興趣的可以了解下
    2024-04-04
  • Go實(shí)現(xiàn)比較時(shí)間大小

    Go實(shí)現(xiàn)比較時(shí)間大小

    這篇文章主要介紹了Go實(shí)現(xiàn)比較時(shí)間大小的方法和示例,非常的簡(jiǎn)單實(shí)用,有需要的小伙伴可以參考下。
    2015-04-04
  • Golang實(shí)現(xiàn)IO操作

    Golang實(shí)現(xiàn)IO操作

    本文主要介紹了Golang實(shí)現(xiàn)IO操作,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-05-05
  • 淺析Go語言中的同步與異步處理

    淺析Go語言中的同步與異步處理

    在開發(fā)過程中,當(dāng)需要同時(shí)處理多個(gè)操作時(shí),開發(fā)者經(jīng)常面臨同步和異步兩種處理方式的選擇,下面小編就來和大家詳細(xì)介紹一下Go語言中的同步與異步處理吧
    2023-11-11
  • GO語言基礎(chǔ)入門第一個(gè)go程序解讀

    GO語言基礎(chǔ)入門第一個(gè)go程序解讀

    這篇文章主要為大家介紹了GO語言基礎(chǔ)入門的第一個(gè)go程序解讀,下面來帶大家進(jìn)入Go語言世界helloworld的大門吧,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2021-11-11
  • Go?iota關(guān)鍵字與枚舉類型實(shí)現(xiàn)原理

    Go?iota關(guān)鍵字與枚舉類型實(shí)現(xiàn)原理

    這篇文章主要介紹了Go?iota關(guān)鍵字與枚舉類型實(shí)現(xiàn)原理,iota是go語言的常量計(jì)數(shù)器,只能在常量的表達(dá)式中使用,更多相關(guān)內(nèi)容需要的小伙伴可以參考一下
    2022-07-07
  • 初步解讀Golang中的接口相關(guān)編寫方法

    初步解讀Golang中的接口相關(guān)編寫方法

    這篇文章主要介紹了Golang中的接口相關(guān)編寫方法,是Go語言入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-11-11
  • Golang Copier入門到入坑探究

    Golang Copier入門到入坑探究

    這篇文章主要為大家介紹了Golang Copier入門到入坑探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • Golang?編寫Tcp服務(wù)器的解決方案

    Golang?編寫Tcp服務(wù)器的解決方案

    Golang?作為廣泛用于服務(wù)端和云計(jì)算領(lǐng)域的編程語言,tcp?socket?是其中至關(guān)重要的功能,這篇文章給大家介紹Golang?開發(fā)?Tcp?服務(wù)器及拆包粘包、優(yōu)雅關(guān)閉的解決方案,感興趣的朋友一起看看吧
    2022-10-10

最新評(píng)論

清水县| 天水市| 萍乡市| 阳曲县| 瓦房店市| 错那县| 曲麻莱县| 合水县| 罗江县| 宁明县| 库伦旗| 马公市| 北流市| 沁水县| 佛冈县| 嘉峪关市| 威海市| 张家川| 鄂州市| 本溪| 阿鲁科尔沁旗| 奉节县| 宜兴市| 思南县| 高邑县| 射阳县| 临沭县| 北流市| 中牟县| 深水埗区| 丰顺县| 醴陵市| 耒阳市| 南投市| 阿城市| 额尔古纳市| 南通市| 玉溪市| 商河县| 梅州市| 盐池县|