func (formatter *formatter) Format(message string, level LogLevel, context LogContextInterface) string {
	if len(formatter.formatterFuncs) == 0 {
		return formatter.fmtString
	}
	params := make([]interface{}, len(formatter.formatterFuncs))
	for i, function := range formatter.formatterFuncs {
		params[i] = function(message, level, context)
	}
	return fmt.Sprintf(formatter.fmtString, params...)
}
Format processes a message with special formatters, log level, and context. Returns formatted string
with all formatter identifiers changed to appropriate values.
package seelog
import (
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"
	"unicode"
	"unicode/utf8"
)
const (
	FormatterSymbol = '%'
)
const (
	formatterSymbolString   = "%"
	formatterParameterStart = '('
	formatterParameterEnd   = ')'
)
const (
	DateDefaultFormat = "2006-01-02"
	TimeFormat        = "15:04:05"
)
var DefaultMsgFormat = "%Ns [%Level] %Msg%n"
var defaultformatter *formatter
var msgonlyformatter *formatter
func init() {
	var err error
	defaultformatter, err = newFormatter(DefaultMsgFormat)
	if err != nil {
		fmt.Println("Error during defaultformatter creation: " + err.Error())
	}
	msgonlyformatter, err = newFormatter("%Msg")
	if err != nil {
		fmt.Println("Error during msgonlyformatter creation: " + err.Error())
	}
}
type FormatterFunc func(message string, level LogLevel, context LogContextInterface) interface{}
type FormatterFuncCreator func(param string) FormatterFunc
var formatterFuncs = map[string]FormatterFunc{
	"Level":     formatterLevel,
	"Lev":       formatterLev,
	"LEVEL":     formatterLEVEL,
	"LEV":       formatterLEV,
	"l":         formatterl,
	"Msg":       formatterMsg,
	"FullPath":  formatterFullPath,
	"File":      formatterFile,
	"RelFile":   formatterRelFile,
	"Func":      FormatterFunction,
	"FuncShort": FormatterFunctionShort,
	"Line":      formatterLine,
	"Time":      formatterTime,
	"UTCTime":   formatterUTCTime,
	"Ns":        formatterNs,
	"UTCNs":     formatterUTCNs,
	"n":         formattern,
	"t":         formattert,
}
var formatterFuncsParameterized = map[string]FormatterFuncCreator{
	"Date":    createDateTimeFormatterFunc,
	"UTCDate": createUTCDateTimeFormatterFunc,
	"EscM":    createANSIEscapeFunc,
}
func errorAliasReserved(name string) error {
	return fmt.Errorf("Cannot use '%s' as custom formatter name. Name is reserved.", name)
}
func RegisterCustomFormatter(name string, creator FormatterFuncCreator) error {
	if _, ok := formatterFuncs[name]; ok {
		return errorAliasReserved(name)
	}
	if _, ok := formatterFuncsParameterized[name]; ok {
		return errorAliasReserved(name)
	}
	formatterFuncsParameterized[name] = creator
	return nil
}
type formatter struct {
	fmtStringOriginal string
	fmtString         string
	formatterFuncs    []FormatterFunc
}
func newFormatter(formatString string) (*formatter, error) {
	newformatter := new(formatter)
	newformatter.fmtStringOriginal = formatString
	err := newformatter.buildFormatterFuncs()
	if err != nil {
		return nil, err
	}
	return newformatter, nil
}
func (formatter *formatter) buildFormatterFuncs() error {
	formatter.formatterFuncs = make([]FormatterFunc, 0)
	var fmtString string
	for i := 0; i < len(formatter.fmtStringOriginal); i++ {
		char := formatter.fmtStringOriginal[i]
		if char != FormatterSymbol {
			fmtString += string(char)
			continue
		}
		isEndOfStr := i == len(formatter.fmtStringOriginal)-1
		if isEndOfStr {
			return errors.New(fmt.Sprintf("Format error: %v - last symbol", formatterSymbolString))
		}
		isDoubledFormatterSymbol := formatter.fmtStringOriginal[i+1] == FormatterSymbol
		if isDoubledFormatterSymbol {
			fmtString += formatterSymbolString
			i++
			continue
		}
		function, nextI, err := formatter.extractFormatterFunc(i + 1)
		if err != nil {
			return err
		}
		fmtString += "%v"
		i = nextI
		formatter.formatterFuncs = append(formatter.formatterFuncs, function)
	}
	formatter.fmtString = fmtString
	return nil
}
func (formatter *formatter) extractFormatterFunc(index int) (FormatterFunc, int, error) {
	letterSequence := formatter.extractLetterSequence(index)
	if len(letterSequence) == 0 {
		return nil, 0, errors.New(fmt.Sprintf("Format error: lack of formatter after %v. At %v", formatterSymbolString, index))
	}
	function, formatterLength, ok := formatter.findFormatterFunc(letterSequence)
	if ok {
		return function, index + formatterLength - 1, nil
	}
	function, formatterLength, ok = formatter.findFormatterFuncParametrized(letterSequence, index)
	if ok {
		return function, index + formatterLength - 1, nil
	}
	return nil, 0, errors.New("Format error: unrecognized formatter at " + strconv.Itoa(index) + ": " + letterSequence)
}
func (formatter *formatter) extractLetterSequence(index int) string {
	letters := ""
	bytesToParse := []byte(formatter.fmtStringOriginal[index:])
	runeCount := utf8.RuneCount(bytesToParse)
	for i := 0; i < runeCount; i++ {
		rune, runeSize := utf8.DecodeRune(bytesToParse)
		bytesToParse = bytesToParse[runeSize:]
		if unicode.IsLetter(rune) {
			letters += string(rune)
		} else {
			break
		}
	}
	return letters
}
func (formatter *formatter) findFormatterFunc(letters string) (FormatterFunc, int, bool) {
	currentVerb := letters
	for i := 0; i < len(letters); i++ {
		function, ok := formatterFuncs[currentVerb]
		if ok {
			return function, len(currentVerb), ok
		}
		currentVerb = currentVerb[:len(currentVerb)-1]
	}
	return nil, 0, false
}
func (formatter *formatter) findFormatterFuncParametrized(letters string, lettersStartIndex int) (FormatterFunc, int, bool) {
	currentVerb := letters
	for i := 0; i < len(letters); i++ {
		functionCreator, ok := formatterFuncsParameterized[currentVerb]
		if ok {
			paramter := ""
			parameterLen := 0
			isVerbEqualsLetters := i == 0  
			if isVerbEqualsLetters {
				userParamter := ""
				userParamter, parameterLen, ok = formatter.findparameter(lettersStartIndex + len(currentVerb))
				if ok {
					paramter = userParamter
				}
			}
			return functionCreator(paramter), len(currentVerb) + parameterLen, true
		}
		currentVerb = currentVerb[:len(currentVerb)-1]
	}
	return nil, 0, false
}
func (formatter *formatter) findparameter(startIndex int) (string, int, bool) {
	if len(formatter.fmtStringOriginal) == startIndex || formatter.fmtStringOriginal[startIndex] != formatterParameterStart {
		return "", 0, false
	}
	endIndex := strings.Index(formatter.fmtStringOriginal[startIndex:], string(formatterParameterEnd)) + startIndex
	if endIndex == -1 {
		return "", 0, false
	}
	length := endIndex - startIndex + 1
	return formatter.fmtStringOriginal[startIndex+1 : endIndex], length, true
}