初始版本
diff --git a/golog.go b/golog.go
new file mode 100644
index 0000000..fd59e07
--- /dev/null
+++ b/golog.go
@@ -0,0 +1,216 @@
+package golog
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"os"
+	"path/filepath"
+	"time"
+
+	log "github.com/go-playground/log"
+)
+
+var logLevelsArray = []log.Level{log.DebugLevel,
+	log.TraceLevel,
+	log.InfoLevel,
+	log.NoticeLevel,
+	log.WarnLevel,
+	log.ErrorLevel,
+	log.PanicLevel,
+	log.AlertLevel,
+	log.FatalLevel}
+
+func getLogLevels(l log.Level) []log.Level {
+	levels := make([]log.Level, 0)
+	offset := int(l)
+	levels = append(levels, logLevelsArray[offset:]...)
+	return levels
+}
+
+func RegisterHandler(handler log.Handler, l log.Level) {
+	log.RegisterHandler(handler, getLogLevels(l)...)
+}
+
+type BaseLogHandler struct {
+}
+
+func (l *BaseLogHandler) FormatMessage(e *log.Entry, w io.Writer) {
+	now := e.Timestamp.In(time.Local)
+	fmt.Fprintf(w, "[%s] %s - %s", e.Level,
+		now.Format(l.getDefaultTimeLayout()), e.Message)
+	for _, f := range e.Fields {
+		fmt.Fprintf(w, " %s=%v", f.Key, f.Value)
+	}
+	w.Write([]byte("\n"))
+}
+
+func (l *BaseLogHandler) getDefaultTimeLayout() string {
+	return "2006-01-02 15:04:05.000"
+}
+
+type FileLogHandler struct {
+	*BaseLogHandler
+	logFilePath string
+	logHandler  *os.File
+}
+
+func checkAndCreateDir(path string) error {
+	if _, err := os.Stat(path); err != nil && os.IsNotExist(err) {
+		if err = os.MkdirAll(path, os.ModeDir|os.ModePerm); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func NewFileLogHandler(logPath string) *FileLogHandler {
+	res := new(FileLogHandler)
+	res.logFilePath = logPath
+	return res
+}
+
+func (h *FileLogHandler) openLogFile() error {
+	dir := filepath.Dir(h.logFilePath)
+	var err error
+	if err = checkAndCreateDir(dir); err != nil {
+		return err
+	}
+	if h.logHandler, err = os.OpenFile(h.logFilePath,
+		os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (h *FileLogHandler) Run() chan<- *log.Entry {
+	if err := h.openLogFile(); err != nil {
+		panic(fmt.Sprintf("Can't open log file, Err=%v\n", err))
+	}
+	ch := make(chan *log.Entry, 5)
+	go func(entries <-chan *log.Entry) {
+		var e *log.Entry
+		b := new(bytes.Buffer)
+		defer h.logHandler.Close()
+		for e = range entries {
+
+			b.Reset()
+			h.FormatMessage(e, b)
+			io.Copy(h.logHandler, b)
+			h.logHandler.Sync()
+			e.Consumed()
+		}
+	}(ch)
+	return ch
+}
+
+type RotateFileLogHandler struct {
+	*BaseLogHandler
+	logFilePath     string
+	maxLogSize      int64
+	maxLogFileCount int
+	logCurrentSize  int64
+	logHandler      *os.File
+}
+
+// NewRotateFileLogHandler
+// maxSize in MB
+func NewRotateFileLogHandler(logPath string, maxSize int, maxCount int) *RotateFileLogHandler {
+	res := new(RotateFileLogHandler)
+	res.logFilePath = logPath
+	if maxSize < 1 || maxSize > 2000 {
+		maxSize = 50
+	}
+	res.maxLogFileCount = maxCount
+	res.maxLogSize = int64(maxSize) * 1024 * 1024
+	return res
+}
+
+func (h *RotateFileLogHandler) checkFile() error {
+	var err error
+	dir := filepath.Dir(h.logFilePath)
+	if err = checkAndCreateDir(dir); err != nil {
+		return err
+	}
+	if h.logHandler, err = os.OpenFile(h.logFilePath,
+		os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666); err != nil {
+		return err
+	}
+	h.logHandler.Seek(0, os.SEEK_SET)
+	n, _ := h.logHandler.Seek(0, os.SEEK_END)
+	h.logCurrentSize = n
+	return nil
+}
+
+func (h *RotateFileLogHandler) rotate() error {
+	var backupFilePath string
+	minModTime := time.Now()
+	backupExists := true
+	for i := 0; i < h.maxLogFileCount; i++ {
+		fullPath := fmt.Sprintf("%v.%d", h.logFilePath, i+1)
+		if stat, err := os.Stat(fullPath); err != nil {
+			if os.IsNotExist(err) {
+				backupFilePath = fullPath
+				backupExists = false
+				break
+			} else {
+				return err
+			}
+		} else {
+			if stat.ModTime().Before(minModTime) {
+				minModTime = stat.ModTime()
+				backupFilePath = fullPath
+			}
+		}
+	}
+	if backupExists && len(backupFilePath) > 0 {
+		os.Remove(backupFilePath)
+	}
+	if len(backupFilePath) > 0 {
+		var err error
+		h.logHandler.Close()
+		h.logHandler = nil
+		err = os.Rename(h.logFilePath, backupFilePath)
+		if err != nil {
+			fmt.Printf("Rename file Error=%v\n", err)
+		}
+		//		if stat, err := os.Stat(backupFilePath); err == nil {
+		//			fmt.Printf("Backup file size:<%v>%v\n", backupFilePath, stat.Size())
+		//		}
+		h.logHandler, err = os.OpenFile(h.logFilePath,
+			os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0660)
+		if err != nil {
+			return err
+		}
+		h.logCurrentSize = 0
+	}
+	return nil
+}
+
+func (h *RotateFileLogHandler) Run() chan<- *log.Entry {
+	if err := h.checkFile(); err != nil {
+		panic(fmt.Sprintf("Can't create file, Err=%v", err))
+	}
+	ch := make(chan *log.Entry, 5)
+	go func(entries <-chan *log.Entry) {
+		var e *log.Entry
+		b := new(bytes.Buffer)
+		defer h.logHandler.Close()
+		for e = range entries {
+
+			b.Reset()
+			h.FormatMessage(e, b)
+			h.logCurrentSize += int64(b.Len())
+			if h.logHandler != nil {
+				io.Copy(h.logHandler, b)
+				// h.logHandler.Sync()
+				if h.logCurrentSize >= h.maxLogSize {
+					//fmt.Printf("Current Size=%v, old=%v\n", h.logCurrentSize, h.maxLogSize)
+					h.rotate()
+				}
+			}
+			e.Consumed()
+		}
+	}(ch)
+	return ch
+}