ioprogress

基本信息

原理

ioprogress定义了实现了自己的Reader,每次调用Read方法时,就会触发绘制进度。

func (r *Reader) Read(p []byte) (int, error) {
    ...

    n, err := r.Reader.Read(p)

    ...
    if err == nil {
        if n > 0 {
            r.drawProgress()
        }
    }
    if err == io.EOF {
        r.finishProgress()
    }

    return n, err
}

比如readme中示例的io.Copy,因为io.Copy(dst Writer, src Reader)是一直拷贝src到dst,我们把自定义的Reader传进去,
每次Read的时候,就会调用Reader.Read,就是我们实现的READ方法,就会有进度条了。

// Imagine this came from some external source, such as a network connection,
// and that we have the full size of it, such as from a Content-Length HTTP
// header.
var r io.Reader

// Create the progress reader
progressR := &ioprogress.Reader{
    Reader: r,
    Size:   rSize,
}

// Copy all of the reader to some local file f. As it copies, the
// progressR will write progress to the terminal on os.Stdout. This is
// customizable.
io.Copy(f, progressR)

关于绘制函数,定义是type DrawFunc func(int64, int64) error,我们可以学习下如何封装抽象,提供最大的灵活性。

首先是定义了func DrawTerminalf(w io.Writer, f DrawTextFormatFunc) DrawFunc
type DrawTextFormatFunc func(int64, int64) string。DrawTextFormatFunc主要的职责是传入当前进度和总共,返回要绘制的字符串表示。
DrawTerminalf函数接受一个Writer(比如os.Stdout)和DrawTextFormatFunc,包装返回DrawFunc。

type DrawFunc func(int64, int64) error

// DrawTextFormatFunc is a callback used by DrawFuncs that draw text in
// order to format the text into some more human friendly format.
type DrawTextFormatFunc func(int64, int64) string

var defaultDrawFunc DrawFunc

func init() {
    defaultDrawFunc = DrawTerminal(os.Stdout)
}

// DrawTerminalf returns a DrawFunc that draws a progress bar to an io.Writer
// that is formatted with the given formatting function.
func DrawTerminalf(w io.Writer, f DrawTextFormatFunc) DrawFunc {
    ...
}

官方提供的DrawTextFormatFunc有3个,一个是最简单的,另外两个是DrawTextFormatBar,DrawTextFormatBytes。

所以最终的使用方式就变成了:
1. 如果不指定,用默认的defaultDrawFuncDrawTerminal(os.Stdout)
2. 如果想用简单形式,但是希望指定Writer,可以调用DrawTerminal(w io.Writer)自己传入Writer。
3. 如果希望进度条使用其他格式,自己调用func DrawTerminalf(w io.Writer, f DrawTextFormatFunc) DrawFunc,传入官方提供的
DrawTextFormatBar或者DrawTextFormatBytes
4. 还是不满足就自己实现接口就好。

不错的学习点