做网站用html好还是vue好,做一个卖东西的网站,wordpress婚礼模板下载,营销策划方案4000字理解底层— —Golang的log库#xff0c;实现自定义Logger
1 分析实现思路 基于golang中自带的log库实现#xff1a;对日志实现设置日志级别#xff0c;每天生成一个文件#xff0c;同时添加上前缀以及展示文件名等 日志级别#xff0c;通过添加prefix#xff1a;[INFO]、…理解底层— —Golang的log库实现自定义Logger
1 分析实现思路 基于golang中自带的log库实现对日志实现设置日志级别每天生成一个文件同时添加上前缀以及展示文件名等 日志级别通过添加prefix[INFO]、[DEBUG]等来实现每天生成一个日志文件写日志之前判断当前时间是否为新的一天日志文件命名获取每天的时间来实现命名同时添加读写锁保证并发安全获取调用日志文件代码行数及文件名runtime.Caller获取函数调用栈
2 实战
2.1 server.go
package mainimport myTest/inter/log_pro/loggerfunc main() {logger.SetFile(/Users/xsky/GolandProjects/MyTest/inter/log_pro/log/demo.log)logger.SetLevel(0)logger.Debug(hello %s, ziyi)logger.Info(hello %s, ziyi)
}
2.2 logger.go
package loggerimport (logosruntimestrconvstringssynctime
)//基于log库自定义实现logger
var (infoLogger *log.LoggerdebugLogger *log.LoggerlogOut *os.FilelogLevel intcurrentDay int //每天生成一个日志文件logFile stringfileLock sync.RWMutex //读写锁保证同一时间只有一个协程重命名文件
)const (DebugLevel iota //0InfoLevel //1
)func SetLevel(level int) {logLevel level
}func init() {fileLock sync.RWMutex{}
}func SetFile(file string) {var err errorlogOut, err os.OpenFile(file, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0664)if err ! nil {panic(err)} else {//初始化自定义的Logger基于golang中的log库//log.LstdFlags表示时间格式等//log.Llongfile表示文件名及调用代码的位置,log.Llongfile》改为通过getCallTrace获取前缀currentDay time.Now().YearDay()infoLogger log.New(logOut, [INFO] , log.LstdFlags)debugLogger log.New(logOut, [DEBUG] , log.LstdFlags)logFile file}
}func checkIfDayChange() {fileLock.Lock()defer fileLock.Unlock()day : time.Now().YearDay()if day currentDay {return} else {//关闭之前的文件重命名并生成新的文件logOut.Close()postFix : time.Now().Add(-24 * time.Hour).Format(20060102)err : os.Rename(logFile, logFile.postFix)if err ! nil {//TODO 重命名日志文件失败根据自身情况做处理}logOut, err os.OpenFile(logFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0664)if err ! nil {//TODO 打开新的日志文件失败根据自己业务需求做处理}infoLogger log.New(logOut, [INFO] , log.LstdFlags)debugLogger log.New(logOut, [DEBUG] , log.LstdFlags)currentDay day}
}//golang中的any相当于interface{}空接口
func Debug(format string, v ...any) {if logLevel DebugLevel {checkIfDayChange()debugLogger.Printf(getPrefix()format, v)}
}func Info(format string, v ...any) {if logLevel InfoLevel {checkIfDayChange()infoLogger.Printf(getPrefix()format, v)}
}//获取函数调用栈关系拿到调用Info或者Debug所在的文件名及代码行数runtime包
func getCallTrace() (string, int) {_, file, lineNo, ok : runtime.Caller(3)if ok {return file, lineNo} else {return , 0}
}//获取调用Info、Debug代码所在行数文件名只获取最后三级
func getPrefix() string {file, lineNo : getCallTrace()path : strings.Split(file, /)if len(path) 3 {file strings.Join(path[len(path)-3:], /)}return file : strconv.Itoa(lineNo)
}3 效果 运行server.go查看效果 目录结构