GO自带日志库log包解释
GO自带日志库log包解释
package mainimport ("log""os"
)func init() {// 配置日志输出格式log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)// 配置前缀log.SetPrefix("order:")// 配置输出位置logFile, err := os.OpenFile("./test.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)if err != nil {log.Panic("打开日志文件异常")}log.SetOutput(logFile)
}func main() {log.Println("golang技术栈-老郭,log标准库测试")
}
下面按执行顺序,把 testdata/demo.go
的 20 来行代码逐句拆开讲,尤其聚焦在标准库 log
的用法上。先整体看下文件结构:
- 导入包
init()
:程序启动时自动运行,用来做日志系统的“一次性配置”main()
:业务入口,实际写一条日志
──────────────────────
- 导入区
import ("log""os"
)
log
:Go 自带的轻量级日志库,开箱即用。os
:用来跟操作系统交互,这里主要用来打开(或创建)日志文件。
──────────────────────
2. init()
函数 —— 日志系统的“装修阶段”
init()
在 main()
之前自动且只执行一次,常用于配置全局资源。下面 3 步骤依次完成“格式”“前缀”“输出目标”的设置。
a) 配置日志格式:log.SetFlags
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
log.SetFlags
接收一个 bitmask,决定每条日志前面要自动加哪些信息。
log.Ldate
→2006/01/02
log.Ltime
→15:04:05
log.Lshortfile
→文件名:行号
(例如demo.go:18
)。
用|
把三项“或”在一起,所以最终日志行会长这样:
2024/06/10 15:30:21 demo.go:18 your message...
如果不调用 SetFlags
,默认只带 Ldate | Ltime
。
b) 配置统一前缀:log.SetPrefix
log.SetPrefix("order:")
给所有日志行再添一个字符串前缀,这里写了 "order:"
。继续延伸刚才示例:
order:2024/06/10 15:30:21 demo.go:18 your message...
常用来区分不同模块或组件打出的日志。
c) 把日志写到文件:log.SetOutput
logFile, err := os.OpenFile("./test.log",os.O_CREATE|os.O_WRONLY|os.O_APPEND,0644)
...
log.SetOutput(logFile)
解释这几行:
-
os.OpenFile
打开或创建./test.log
。
•os.O_CREATE
:如果文件不存在就创建。
•os.O_WRONLY
:只写。
•os.O_APPEND
:每次写都追加到文件末尾,不会覆盖旧内容。
权限0644
:文件所有者可读写,组和其他用户只读。 -
错误处理:若返回
err != nil
,直接log.Panic(...)
。log.Panic
会打印信息后触发 panic,程序立即中断。这算是简单暴力的“初始化失败立刻退出”。 -
log.SetOutput(logFile)
把 log 的默认输出从 “终端的 stderr” 改成了test.log
文件。所以之后的log.Println
都会写入该文件,而不是显示在控制台。
──────────────────────
3. main()
—— 正式写一条日志
func main() {log.Println("golang技术栈-老郭,log标准库测试")
}
log.Println
等价fmt.Println
+前缀+换行,会按照刚才配置好的“前缀 + 时间 + 文件行号”格式输出。- 因为
SetOutput
指向了test.log
,所以这行文字会被追加到日志文件末尾,而不是打印在终端。
──────────────────────
关键知识点小结
-
log 包四大基本函数
•SetFlags(bitmask)
:决定“固定装饰信息”
•SetPrefix(string)
:统一前缀
•SetOutput(io.Writer)
:输出目的地(默认 stderr,可改成文件、网络、甚至多路复用 writer)
• 各种写日志:Print/Printf/Println
,Fatal*
(写完后os.Exit(1)
),Panic*
(写完后panic
) -
为什么放在
init()
?
Go 会在main()
之前依次执行所有文件里的init()
,适合做一次性全局配置;写在这里不会被业务逻辑误删或漏写。 -
文件句柄要不要关闭?
严格来说,程序结束前最好defer logFile.Close()
;不过 Demo 很短,进程结束时内核会回收句柄。 -
如果要按天分割日志或增加日志级别(INFO/WARN/ERROR),
log
包本身就不支持,需要再封一层或改用社区库(如logrus
,zap
,zerolog
等)。
这样,你就清晰地了解了如何利用 Go 标准库 log
在几行代码内完成“日志格式化 + 自定义前缀 + 输出到文件”的常见需求。