func (pb *ProgressBar) Get(key interface{}) interface{} {
	pb.mu.RLock()
	defer pb.mu.RUnlock()
	if pb.vars == nil {
		return nil
	}
	return pb.vars[key]
}
Get return value by key
package pb
import (
	"bytes"
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"text/template"
	"time"
	"github.com/fatih/color"
	"github.com/mattn/go-colorable"
	"github.com/mattn/go-isatty"
	"github.com/cheggaaa/pb/v3/termutil"
)
const Version = "3.0.8"
type key int
const (
	Bytes key = 1 << iota
	SIBytesPrefix
	Terminal
	Static
	ReturnSymbol
	Color
	CleanOnFinish
	TimeRound
)
const (
	defaultBarWidth    = 100
	defaultRefreshRate = time.Millisecond * 200
)
func New(total int) *ProgressBar {
	return New64(int64(total))
}
func New64(total int64) *ProgressBar {
	pb := new(ProgressBar)
	return pb.SetTotal(total)
}
func StartNew(total int) *ProgressBar {
	return New(total).Start()
}
func Start64(total int64) *ProgressBar {
	return New64(total).Start()
}
var (
	terminalWidth    = termutil.TerminalWidth
	isTerminal       = isatty.IsTerminal
	isCygwinTerminal = isatty.IsCygwinTerminal
)
type ProgressBar struct {
	current, total int64
	width          int
	maxWidth       int
	mu             sync.RWMutex
	rm             sync.Mutex
	vars           map[interface{}]interface{}
	elements       map[string]Element
	output         io.Writer
	coutput        io.Writer
	nocoutput      io.Writer
	startTime      time.Time
	refreshRate    time.Duration
	tmpl           *template.Template
	state          *State
	buf            *bytes.Buffer
	ticker         *time.Ticker
	finish         chan struct{}
	finished       bool
	configured     bool
	err            error
}
func (pb *ProgressBar) configure() {
	if pb.configured {
		return
	}
	pb.configured = true
	if pb.vars == nil {
		pb.vars = make(map[interface{}]interface{})
	}
	if pb.output == nil {
		pb.output = os.Stderr
	}
	if pb.tmpl == nil {
		pb.tmpl, pb.err = getTemplate(string(Default))
		if pb.err != nil {
			return
		}
	}
	if pb.vars[Terminal] == nil {
		if f, ok := pb.output.(*os.File); ok {
			if isTerminal(f.Fd()) || isCygwinTerminal(f.Fd()) {
				pb.vars[Terminal] = true
			}
		}
	}
	if pb.vars[ReturnSymbol] == nil {
		if tm, ok := pb.vars[Terminal].(bool); ok && tm {
			pb.vars[ReturnSymbol] = "\r"
		}
	}
	if pb.vars[Color] == nil {
		if tm, ok := pb.vars[Terminal].(bool); ok && tm {
			pb.vars[Color] = true
		}
	}
	if pb.refreshRate == 0 {
		pb.refreshRate = defaultRefreshRate
	}
	if pb.vars[CleanOnFinish] == nil {
		pb.vars[CleanOnFinish] = false
	}
	if f, ok := pb.output.(*os.File); ok {
		pb.coutput = colorable.NewColorable(f)
	} else {
		pb.coutput = pb.output
	}
	pb.nocoutput = colorable.NewNonColorable(pb.output)
}
func (pb *ProgressBar) Start() *ProgressBar {
	pb.mu.Lock()
	defer pb.mu.Unlock()
	if pb.finish != nil {
		return pb
	}
	pb.configure()
	pb.finished = false
	pb.state = nil
	pb.startTime = time.Now()
	if st, ok := pb.vars[Static].(bool); ok && st {
		return pb
	}
	pb.finish = make(chan struct{})
	pb.ticker = time.NewTicker(pb.refreshRate)
	go pb.writer(pb.finish)
	return pb
}
func (pb *ProgressBar) writer(finish chan struct{}) {
	for {
		select {
		case <-pb.ticker.C:
			pb.write(false)
		case <-finish:
			pb.ticker.Stop()
			pb.write(true)
			finish <- struct{}{}
			return
		}
	}
}
func (pb *ProgressBar) Write() *ProgressBar {
	pb.mu.RLock()
	finished := pb.finished
	pb.mu.RUnlock()
	pb.write(finished)
	return pb
}
func (pb *ProgressBar) write(finish bool) {
	result, width := pb.render()
	if pb.Err() != nil {
		return
	}
	if pb.GetBool(Terminal) {
		if r := (width - CellCount(result)); r > 0 {
			result += strings.Repeat(" ", r)
		}
	}
	if ret, ok := pb.Get(ReturnSymbol).(string); ok {
		result = ret + result
		if finish && ret == "\r" {
			if pb.GetBool(CleanOnFinish) {
				result = "\r" + color.New(color.Reset).Sprintf(strings.Repeat(" ", width)) + "\r"
			} else {
				result += "\n"
			}
		}
	}
	if pb.GetBool(Color) {
		pb.coutput.Write([]byte(result))
	} else {
		pb.nocoutput.Write([]byte(result))
	}
}
func (pb *ProgressBar) Total() int64 {
	return atomic.LoadInt64(&pb.total)
}
func (pb *ProgressBar) SetTotal(value int64) *ProgressBar {
	atomic.StoreInt64(&pb.total, value)
	return pb
}
func (pb *ProgressBar) AddTotal(value int64) *ProgressBar {
	atomic.AddInt64(&pb.total, value)
	return pb
}
func (pb *ProgressBar) SetCurrent(value int64) *ProgressBar {
	atomic.StoreInt64(&pb.current, value)
	return pb
}
func (pb *ProgressBar) Current() int64 {
	return atomic.LoadInt64(&pb.current)
}
func (pb *ProgressBar) Add64(value int64) *ProgressBar {
	atomic.AddInt64(&pb.current, value)
	return pb
}
func (pb *ProgressBar) Add(value int) *ProgressBar {
	return pb.Add64(int64(value))
}
func (pb *ProgressBar) Increment() *ProgressBar {
	return pb.Add64(1)
}
func (pb *ProgressBar) Set(key, value interface{}) *ProgressBar {
	pb.mu.Lock()
	defer pb.mu.Unlock()
	if pb.vars == nil {
		pb.vars = make(map[interface{}]interface{})
	}
	pb.vars[key] = value
	return pb
}