Go 语言零基础入门:标准库 log 包完全教程
作为 Go 开发者,日志是我们排查问题、监控程序运行的核心工具。Go 语言内置了开箱即用的标准库 log,无需安装任何第三方包,一行代码就能打印日志,非常适合零基础入门和小型项目使用。
这篇文章会从零开始,带你全面掌握 Go 标准日志库的所有核心用法,每个代码示例都附带运行结果 + 结果解释,看完就能直接在项目中落地使用。
一、什么是 log 包?
log 是 Go 语言标准库自带的日志包 ,位于 log 目录下,核心作用:
- 打印程序运行日志、错误信息、调试信息
- 支持输出到控制台、文件、自定义输出流
- 自带时间、文件名、行号等日志前缀
- 轻量无依赖,所有 Go 环境直接使用
它的定位是轻量基础日志工具,适合学习、小工具、微服务基础日志打印,是 Go 开发者必须掌握的基础技能。
二、快速入门:第一个日志程序
1. 导入包
使用前只需要导入标准库:
go
import "log"
2. 最简单的日志打印
go
package main
// 导入日志包
import "log"
func main() {
// 打印普通日志
log.Println("程序启动成功!")
log.Println("当前正在执行核心逻辑")
}
运行结果
2025/12/18 10:00:00 程序启动成功!
2025/12/18 10:00:00 当前正在执行核心逻辑
结果解释
- Go 标准日志默认自带时间戳 (
2025/12/18 10:00:00),无需手动配置 log.Println()会自动换行,和fmt.Println()用法一致- 直接运行即可输出,无需任何初始化配置
三、log 包核心函数(必学)
log 包提供了 3 组最常用的打印函数,分别对应普通日志、格式化日志、致命错误日志,零基础优先掌握这几组。
1. 普通打印:Print/Println/Printf
这是最常用的日志函数,和 fmt 包用法几乎一致:
Print():直接打印,不自动换行Println():打印并自动换行Printf():格式化打印(支持占位符)
go
package main
import "log"
func main() {
name := "Go日志教程"
version := 1.0
// 普通打印
log.Print("这是 Print 日志")
// 换行打印
log.Println("这是 Println 日志")
// 格式化打印(和 fmt.Printf 用法一样)
log.Printf("课程名称:%s,版本:%.1f", name, version)
}
运行结果
2025/12/18 10:02:30 这是 Print 日志2025/12/18 10:02:30 这是 Println 日志
2025/12/18 10:02:30 课程名称:Go日志教程,版本:1.0
结果解释
log.Print()不会自动换行,所以两条日志连在了一起log.Println()自动换行,格式更清晰log.Printf()支持%s(字符串)、%f(浮点数)等占位符,格式化输出变量
2. 致命错误日志:Fatal/Fatalln/Fatalf
作用 :打印日志后,直接终止程序 (等价于 print() + os.Exit(1))。
适合:程序遇到无法恢复的严重错误(如配置文件丢失、数据库连接失败)。
go
package main
import "log"
func main() {
// 打印错误信息并退出程序
log.Fatalln("数据库连接失败,程序退出!")
// 这行代码永远不会执行
log.Println("程序继续运行")
}
运行结果
2025/12/18 10:03:10 数据库连接失败,程序退出!
结果解释
- 执行
log.Fatalln()后,程序直接退出 - 后面的
log.Println("程序继续运行")完全不会执行 - 退出码为
1,代表程序异常退出
3. 恐慌日志:Panic/Panicln/Panicf
作用 :打印日志,然后触发 panic(程序崩溃,可被 recover 捕获)。
适合:代码逻辑异常、空指针、数组越界等运行时错误。
go
package main
import "log"
func main() {
log.Panicln("发生严重逻辑错误!")
}
运行结果
2025/12/18 10:04:20 发生严重逻辑错误!
panic: 发生严重逻辑错误!
goroutine 1 [running]:
log.Panicln(0x14000010000?, 0x1?, 0x1?)
结果解释
- 先打印日志信息
- 然后抛出
panic崩溃信息,包含崩溃的代码位置 panic可以用recover()捕获修复,而Fatal不能
四、自定义日志格式(进阶)
默认日志只有时间,我们可以自定义日志前缀、显示文件名/行号、自定义分隔符,让日志更清晰。
1. 设置日志前缀
用 log.SetPrefix() 给所有日志加统一前缀,方便区分服务/模块。
go
package main
import "log"
func main() {
// 设置日志前缀
log.SetPrefix("[订单服务] ")
log.Println("订单创建成功")
log.Println("订单支付完成")
}
运行结果
[订单服务] 2025/12/18 10:05:00 订单创建成功
[订单服务] 2025/12/18 10:05:00 订单支付完成
结果解释
- 所有日志前面都加上了统一前缀
[订单服务] - 多模块项目中,可通过前缀快速区分日志来源
2. 设置日志选项(显示行号、文件名)
用 log.SetFlags() 开启高级日志信息,支持的参数:
log.Ldate:日期(默认)log.Ltime:时间(默认)log.Lmicroseconds:微秒精度log.Llongfile:完整文件路径+行号log.Lshortfile:文件名+行号(推荐)log.LUTC:使用 UTC 时间log.LstdFlags:默认格式(日期+时间)
示例:开启文件名 + 行号 + 时间
go
package main
import "log"
func main() {
// 设置格式:日期 + 时间 + 文件名+行号
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
log.Println("这是带行号的日志")
}
运行结果
2025/12/18 10:10:00 main.go:8 这是带行号的日志
结果解释
- 日志中新增了
main.go:8,代表代码在 main.go 文件第 8 行 - 调试报错时,能直接定位到代码位置,大幅提升效率
3. 组合使用:前缀 + 格式
go
package main
import "log";
func main() {
// 1. 设置前缀
log.SetPrefix("[用户服务] ")
// 2. 设置格式
log.SetFlags(log.LstdFlags | log.Lshortfile)
log.Println("用户登录成功")
}
运行结果
[用户服务] 2025/12/18 10:12:10 main.go:10 用户登录成功
结果解释
- 同时包含服务前缀 + 时间 + 文件名+行号 + 日志内容
- 格式完整,生产环境调试非常实用
五、日志输出到文件(实战必备)
默认日志打印在控制台,生产环境需要把日志保存到文件 ,log 包支持直接输出到文件。
完整示例:日志写入文件
go
package main
import (
"log"
"os";
)
func main() {
// 1. 创建/打开日志文件
logFile, err := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Fatalln("日志文件创建失败:", err)
}
defer logFile.Close()
// 2. 设置日志输出到文件
log.SetOutput(logFile)
// 3. 打印日志
log.Println("程序启动")
log.Println("业务逻辑执行中")
log.Println("程序退出")
}
运行结果(控制台无输出)
(控制台空白)
结果解释
-
控制台不会打印任何内容,所有日志写入
app.log文件 -
打开
app.log文件,内容如下:2025/12/18 10:13:20 程序启动
2025/12/18 10:13:20 业务逻辑执行中
2025/12/18 10:13:20 程序退出 -
os.O_APPEND表示追加写入,不会覆盖之前的日志
六、创建自定义日志器(多日志隔离)
如果你的项目有多个模块 (订单、用户、支付),需要分开打印日志,可以创建多个独立日志器。
使用 log.New() 创建自定义 Logger:
go
package main
import (
"log"
"os";
)
func main() {
// 1. 创建订单服务日志器
orderLog := log.New(os.Stdout, "[订单] ", log.LstdFlags|log.Lshortfile)
// 2. 创建用户服务日志器
userLog := log.New(os.Stdout, "[用户] ", log.LstdFlags|log.Lshortfile)
// 分别打印
orderLog.Println("订单已提交")
userLog.Println("用户已注册")
}
运行结果
[订单] 2025/12/18 10:15:00 main.go:12 订单已提交
[用户] 2025/12/18 10:15:00 main.go:13 用户已注册
结果解释
- 两个日志器完全独立,前缀、格式互不影响
- 多模块项目中,可轻松区分不同模块的日志
- 还可以给不同模块设置不同的日志文件
七、log 包完整使用总结(速查表)
| 函数/方法 | 作用 | 运行特点 |
|---|---|---|
log.Println() |
普通换行日志 | 程序继续运行 |
log.Printf() |
格式化普通日志 | 程序继续运行 |
log.Fatalln() |
打印日志并退出程序 | 直接终止程序 |
log.Panicln() |
打印日志并触发 panic | 程序崩溃,可捕获 |
log.SetPrefix() |
设置日志前缀 | 全局生效 |
log.SetFlags() |
设置日志格式(日期、行号、文件) | 显示更多调试信息 |
log.SetOutput() |
设置日志输出(文件/控制台) | 控制台无输出,写入文件 |
log.New() |
创建自定义独立日志器 | 多模块日志隔离 |
八、log 包适合什么场景?
✅ 推荐使用:
- Go 语言初学者学习
- 小型工具、脚本
- 简单微服务、后台服务
- 快速调试、打印运行信息
❌ 不推荐:
- 大型分布式系统
- 需要结构化日志(JSON)、日志分级(Debug/Info/Warn/Error)
- 需要日志切割、远程上报
大型项目推荐:zap、logrus 等第三方日志库,但学习标准 log 包是基础。
九、零基础完整实战代码
go
package main
import (
"log"
"os";
)
func main() {
// 打开日志文件
file, err := os.OpenFile("server.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Fatalln("日志文件异常:", err)
}
defer file.Close()
// 自定义日志
logger := log.New(file, "[Go服务] ", log.Ldate|log.Ltime|log.Lshortfile)
// 业务日志
logger.Println("服务器启动成功")
logger.Printf("监听端口:%d", 8080)
logger.Println("请求处理完成")
logger.Fatalln("数据库崩溃,程序终止")
}
运行结果
控制台无输出,server.log 文件内容:
[Go服务] 2025/12/18 10:20:10 main.go:18 服务器启动成功
[Go服务] 2025/12/18 10:20:10 main.go:19 监听端口:8080
[Go服务] 2025/12/18 10:20:10 main.go:20 请求处理完成
[Go服务] 2025/12/18 10:20:10 main.go:21 数据库崩溃,程序终止
总结
- Go 标准库
log开箱即用,无需第三方依赖,零基础首选 - 核心函数:
Print/Printf(普通)、Fatal(退出)、Panic(崩溃) - 可自定义前缀、格式、输出文件,满足基础生产需求
- 多模块可用
log.New()创建独立日志器,实现日志隔离 - 每个示例都能直接复制运行,结果清晰易懂
标准日志包是 Go 开发的基础技能,掌握它,你就能轻松给程序添加专业的日志功能啦!