在开发命令行工具的时候,会遇到一些耗时的操作,比如下载一个大文件,这时候如果能给用户一个进度提示,会显得比较友好,因为用户知道自己还要等多久可以,就可以下载好这个文件。
在Go语言中,可以使用第三方库schollz/progressbar来在终端上实现进度条以处理数据。这个库可以帮助您更容易地在终端中显示进度信息。
下载 #
go get -u github.com/schollz/progressbar/v3
简单使用 #
只需要通过Default函数生成一个bar,然后通过它的Add方法增加进度即可。留意这里的100代表进度的最大值。
package main
import (
"github.com/schollz/progressbar/v3"
"time"
)
func main() {
bar := progressbar.Default(100)
for i := 0; i < 100; i++ {
bar.Add(1)
time.Sleep(40 * time.Millisecond)
}
}
监听 IO 操作 #
下载 Golang Mac 安装包并显示进度,代码如下所示:
package main
import (
"fmt"
"github.com/schollz/progressbar/v3"
"io"
"log"
"net/http"
"os"
)
func main() {
golangPkg := "go1.16.4.darwin-amd64.pkg"
url := fmt.Sprintf("https://golang.google.cn/dl/%s", golangPkg)
request, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
log.Fatalln(err)
}
client := http.DefaultClient
resp, err := client.Do(request)
if err != nil {
log.Fatalln(err)
}
file, err := os.OpenFile(golangPkg, os.O_CREATE|os.O_WRONLY, os.ModePerm)
if err != nil {
log.Fatalln(err)
}
pb := progressbar.DefaultBytes(resp.ContentLength, "正在下载")
io.Copy(io.MultiWriter(file, pb), resp.Body)
}
以上代码的进度条使用到的就是基于字节大小计算的进度,用到了 progressbar.DefaultBytes 函数。
并且因为ProcessBar实现了io.Writer接口,所以可以被io.MultiWriter使用,这样在使用io.Copy下载文件的时候,就可以根据已经下载的字节、总的字节数,计算出进度。
在上面的示例中,我们是通过resp.ContentLength来获取文件的大小的,但是有时候,我们无法获取要下载文件的大小,这时候就可以使用-1代表,那么progressbar就会显示一个未知长度的进度条。