核心引擎 · log日志
本篇是Go从零实现ORM框架MyGORM核心篇的第一篇。
目的
Log日志
MyGorm核心实现之log日志记录,一个好的架构,离不开详细日志,否则出现问题的时候抓眼瞎。因此在实现核心功能前,先实现一个简单的log日志记录。
为什么不直接使用原生的 log 库,log 标准库没有日志分级,不打印文件和行号,这就意味着我们很难快速知道是哪个地方发生了错误。
功能
- 支持日志分级。
- 不同层级日志显示时使用不同的颜色区分。
- 显示打印日志代码对应的文件名和行号。
首先使用命令mkdir mygorm
创建一个名为 mygorm文件夹,然后执行 go mod init mygorm
并新建文件 log.go,用于放置和日志相关的代码。
现在的代码结构为:
1 2 3 4
| mygorm/ log/ |--log.go |--go.mod
|
颜色
通常,我们会对不同等级的日志输出不同的颜色来区分。
1 2
| fmt.Printf("\033[1;31;40m%s\033[0m\n","Red.") fmt.Printf("\033[1;37;41m%s\033[0m\n","Red.")
|
第一行是红字黑底,第二行红底白字。
我们来解析\033[1;31;40m%s\033[0m\n
这个字符串中的字符分别代表了什么。
\033
:\
表示转义,\033
表示设置颜色。
[1;31;40m
:定义颜色,[
表示开始颜色设置,m
为颜色设置结束,以 ;
号分隔。1
代码,表示显示方式,31
表示前景颜色(文字的 颜色),40
表示背景颜色。
\033[0m
:表示恢复终端默认样式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| // 前景 背景 颜色 // --------------------------------------- // 30 40 黑色 // 31 41 红色 // 32 42 绿色 // 33 43 黄色 // 34 44 蓝色 // 35 45 紫红色 // 36 46 青蓝色 // 37 47 白色
// 3 位前景色, 4 位背景色
// 代码 意义 // ------------------------- // 0 终端默认设置 // 1 高亮显示 // 4 使用下划线 // 5 闪烁 // 7 反白显示 // 8 不可见
|
根据上面的颜色,我设置了4种日志级别,代码我已经上传github,点击即可跳转。
my-gorm/log/log.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| package log
import ( "io" "log" "os" "sync" )
type LevelFlag uint
const ( DebugLevel LevelFlag = iota InfoLevel WarnLevel ErrorLevel DisableLevel )
var debugLog = log.New(os.Stdout, "\033[1;37;40m[mygorm-debug]", log.Ldate|log.Lmicroseconds|log.Lshortfile) var infoLog = log.New(os.Stdout, "\033[1;32;40m[mygorm-info]", log.Ldate|log.Lmicroseconds|log.Lshortfile) var warnLog = log.New(os.Stdout, "\033[1;33;40m[mygorm-warn]", log.Ldate|log.Lmicroseconds|log.Lshortfile) var errorLog = log.New(os.Stdout, "\033[1;31;40m[mygorm-error]", log.Ldate|log.Lmicroseconds|log.Lshortfile)
var loggers = []*log.Logger{debugLog, infoLog, warnLog, errorLog} var mu sync.Mutex
var ( Debug = debugLog.Println DebugF = debugLog.Printf
Info = infoLog.Println InfoF = infoLog.Printf
Warn = warnLog.Println WarnF = warnLog.Printf
Error = errorLog.Println ErrorF = errorLog.Printf )
func SetLogLevel(level LevelFlag) { mu.Lock() defer mu.Unlock()
for _, logger := range loggers { logger.SetOutput(os.Stdout) }
if level > ErrorLevel { errorLog.SetOutput(io.Discard) }
if level > WarnLevel { warnLog.SetOutput(io.Discard) }
if level > InfoLevel { infoLog.SetOutput(io.Discard) }
if level > DebugLevel { debugLog.SetOutput(io.Discard) }
}
|
my-gorm/log/log_test.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package log
import ( "testing" )
func TestSetLogLevel(t *testing.T) { SetLogLevel(ErrorLevel) Error("error TestSetLogLevel") Info("info TestSetLogLevel") }
func TestSetLogLevel2(t *testing.T) { SetLogLevel(InfoLevel) Error("error TestSetLogLevel2") Info("info TestSetLogLevel") }
|
这样就实现了一个简单的日志级别输出。