func (l *Logger) Critf(msg string, args ...interface{}) {
	if l.IsEnabledFor(CritLevel) {
		file, line := Caller(1)
		l.Log(CritLevel, file, line, msg, args...)
	}
}
Critf logs a critical level message. It uses fmt.Fprintf() to format msg and args.
package golog
import (
	"io"
	"sort"
	"time"
)
type Level uint8
const (
	DebugLevel Level = iota
	InfoLevel
	WarnLevel
	ErrorLevel
	CritLevel
	disabledLevel Level = 255
)
var (
	levelNames = []byte("DIWEC")
	internalLogger *Logger
)
type Record struct {
	level   Level
	date    string
	time    string
	tm      time.Time
	file    string
	line    int
	message string
	args    []interface{}
}
type Logger struct {
	level      Level  
	minLevel   Level  
	handlers   []*Handler
	isInternal bool
}
func NewLogger(lv Level) *Logger {
	return &Logger{level: lv, minLevel: disabledLevel}  
}
func (l *Logger) AddHandler(h *Handler) {
	h.isInternal = l.isInternal
	l.handlers = append(l.handlers, h)
	if h.level < l.minLevel {
		if h.level > l.level {
			l.minLevel = h.level
		} else {
			l.minLevel = l.level
		}
	}
	if len(l.handlers) > 1 {
		sort.Slice(l.handlers, func(i, j int) bool {
			return l.handlers[i].level < l.handlers[j].level
		})
	}
}
func (l *Logger) IsEnabledFor(level Level) bool {
	return l.minLevel <= level
}
func (l *Logger) GetMinLevel() Level {
	return l.minLevel
}
func (l *Logger) Log(lv Level, file string, line int, msg string, args ...interface{}) {
	r := recordPool.Get().(*Record)
	r.level = lv
	if fastTimer.isRunning {
		r.date = fastTimer.date
		r.time = fastTimer.time
	} else {
		r.tm = now()
	}
	r.file = file
	r.line = line
	r.message = msg
	r.args = args
	for _, h := range l.handlers {
		if !h.Handle(r) {
			break
		}
	}
	recordPool.Put(r)
}
func (l *Logger) Close() {
	for _, h := range l.handlers {
		h.Close()
	}
	l.handlers = nil
}
func (l *Logger) Debug(args ...interface{}) {
	if l.IsEnabledFor(DebugLevel) {
		file, line := Caller(1)  
		l.Log(DebugLevel, file, line, "", args...)
	}
}
func (l *Logger) Debugf(msg string, args ...interface{}) {
	if l.IsEnabledFor(DebugLevel) {
		file, line := Caller(1)
		l.Log(DebugLevel, file, line, msg, args...)
	}
}
func (l *Logger) Info(args ...interface{}) {
	if l.IsEnabledFor(InfoLevel) {
		file, line := Caller(1)
		l.Log(InfoLevel, file, line, "", args...)
	}
}
func (l *Logger) Infof(msg string, args ...interface{}) {
	if l.IsEnabledFor(InfoLevel) {
		file, line := Caller(1)
		l.Log(InfoLevel, file, line, msg, args...)
	}
}
func (l *Logger) Warn(args ...interface{}) {
	if l.IsEnabledFor(WarnLevel) {
		file, line := Caller(1)
		l.Log(WarnLevel, file, line, "", args...)
	}
}
func (l *Logger) Warnf(msg string, args ...interface{}) {
	if l.IsEnabledFor(WarnLevel) {
		file, line := Caller(1)
		l.Log(WarnLevel, file, line, msg, args...)
	}
}
func (l *Logger) Error(args ...interface{}) {
	if l.IsEnabledFor(ErrorLevel) {
		file, line := Caller(1)
		l.Log(ErrorLevel, file, line, "", args...)
	}
}
func (l *Logger) Errorf(msg string, args ...interface{}) {
	if l.IsEnabledFor(ErrorLevel) {
		file, line := Caller(1)
		l.Log(ErrorLevel, file, line, msg, args...)
	}
}
func (l *Logger) Crit(args ...interface{}) {
	if l.IsEnabledFor(CritLevel) {
		file, line := Caller(1)
		l.Log(CritLevel, file, line, "", args...)
	}
}