GO自带日志库log包解释

发布于:2025-06-11 ⋅ 阅读:(24) ⋅ 点赞:(0)

GO自带日志库log包解释

package main

import (
	"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 的用法上。先整体看下文件结构:

  1. 导入包
  2. init():程序启动时自动运行,用来做日志系统的“一次性配置”
  3. main():业务入口,实际写一条日志

──────────────────────

  1. 导入区
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.Ldate2006/01/02
  • log.Ltime15: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)

解释这几行:

  1. os.OpenFile 打开或创建 ./test.log
    os.O_CREATE:如果文件不存在就创建。
    os.O_WRONLY:只写。
    os.O_APPEND:每次写都追加到文件末尾,不会覆盖旧内容。
    权限 0644:文件所有者可读写,组和其他用户只读。

  2. 错误处理:若返回 err != nil,直接 log.Panic(...)log.Panic 会打印信息后触发 panic,程序立即中断。这算是简单暴力的“初始化失败立刻退出”。

  3. log.SetOutput(logFile) 把 log 的默认输出从 “终端的 stderr” 改成了 test.log 文件。所以之后的 log.Println 都会写入该文件,而不是显示在控制台。

──────────────────────
3. main() —— 正式写一条日志

func main() {
    log.Println("golang技术栈-老郭,log标准库测试")
}
  • log.Println 等价 fmt.Println+前缀+换行,会按照刚才配置好的“前缀 + 时间 + 文件行号”格式输出。
  • 因为 SetOutput 指向了 test.log,所以这行文字会被追加到日志文件末尾,而不是打印在终端。

──────────────────────
关键知识点小结

  1. log 包四大基本函数
    SetFlags(bitmask):决定“固定装饰信息”
    SetPrefix(string):统一前缀
    SetOutput(io.Writer):输出目的地(默认 stderr,可改成文件、网络、甚至多路复用 writer)
    • 各种写日志:Print/Printf/Println, Fatal*(写完后 os.Exit(1)),Panic*(写完后 panic

  2. 为什么放在 init()
    Go 会在 main() 之前依次执行所有文件里的 init(),适合做一次性全局配置;写在这里不会被业务逻辑误删或漏写。

  3. 文件句柄要不要关闭?
    严格来说,程序结束前最好 defer logFile.Close();不过 Demo 很短,进程结束时内核会回收句柄。

  4. 如果要按天分割日志或增加日志级别(INFO/WARN/ERROR),log 包本身就不支持,需要再封一层或改用社区库(如 logrus, zap, zerolog 等)。

这样,你就清晰地了解了如何利用 Go 标准库 log 在几行代码内完成“日志格式化 + 自定义前缀 + 输出到文件”的常见需求。