// log.Panic函数会输出日志并触发panic,导致程序终止
// log.Panicf函数会格式化输出日志并触发panic,导致程序终止
func LearnLogPanic() {
// 使用defer关键字定义一个匿名函数,该函数会在LearnLogPanic函数结束时执行
// defer func() {
// // 使用recover函数捕获panic,如果捕获到panic,则输出日志
// if r := recover(); r != nil {
// log.Println("recover函数触发, 返回r为:", r)
// }
// }()
// 输出日志
log.Print("Print")
log.Panic("输出日志后触发 panic") // 输出日志后触发 panic
log.Println("Println") // 不会运行到此处
log.Panicf("格式化输出后触发 panic value %d", 42) // 格式化输出后触发 panic
log.Printf("Printf %d", 42)
}
// 循环调用LearnLogPanic函数,直到第十次停止
// 通过实验可知,函数一旦触发panic,函数中后续的代码都不会执行,会直接进行函数结束的操作,
// 此时,如果有使用recover函数,则可以捕获到panic,函数可以正常结束,不会导致程序终止,可以正常循环10次
// 如果没有使用recover函数,则函数会直接进行函数结束的操作,导致程序终止,在第一次触发panic时,函数会直接进行函数结束的操作,导致程序终止,不会进行循环
func LearnLogPanicLoop() {
for i := 0; i < 10; i++ {
LearnLogPanic()
}
}
// log.SetPrefix:设置日志输出的前缀
// log.SetFlags:设置日志的日期,时间,文件名和行号
// log.Ldate:包含日期, log.Ltime:包含时间, log.Lshortfile:包含文件名和行号
func LearnLogSetPrefix() {
log.SetPrefix("[ MyApp ] ")
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
log.Println("This log will be written to stdout with prefix and flags")
}
// 将日志输出到文件
func LearnLogToFile() {
file, err := os.OpenFile("./app.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
defer file.Close()
log.SetOutput(file) // 1.将日志输出到文件
log.SetPrefix("[ MyApp ] ") // 2.设置日志输出的前缀
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) // 3.设置日志的日期,时间,文件名和行号
// 这三个方法等于log.New(file, "[ MyApp ] ", log.Ldate|log.Ltime|log.Lshortfile)
log.Println("This log will be written to app.log")
}
// 什么情况下使用log.Fatal/Fatalf, 什么情况下使用log.Panic/Panicf?
// 1. log.Fatal/Fatalf
// 行为
// 记录一条日志消息到默认输出(或通过 log.SetOutput 设置的输出目标)。
// 调用 os.Exit(1) 立即终止程序运行。
// 不会触发 defer 延迟调用。
// 特点
// 直接退出程序,不执行任何后续代码。
// 更适合用于处理不可恢复的错误,例如关键资源初始化失败、系统级配置错误等。
// 示例:
// 文件打开失败。
// 数据库连接失败。
// 必要的环境变量未设置。
// 2. log.Panic/Panicf
// 行为
// 记录一条日志消息到默认输出(或通过 log.SetOutput 设置的输出目标)。
// 触发 panic,导致程序进入恢复流程(如果存在 defer 的 recover)。`在这里插入代码片`
// 如果没有 recover,程序最终也会终止。
// 特点
// 触发 panic 后,所有延迟调用(defer)都会被执行。
// 更适合用于测试或需要捕获错误并进行恢复的场景。
// 适用场景
// 当程序遇到异常情况,但希望有机会通过 recover 恢复时,使用 log.Panic。
// 通常用于单元测试或复杂业务逻辑中,允许开发者在某些情况下捕获错误并采取补救措施。
// 示例:
// 测试框架中模拟错误。
// 处理可能导致程序崩溃的边界条件。
// 3.注意事项
// 选择合适的退出方式:如果错误是不可恢复的,优先使用 log.Fatal;如果需要捕获错误并恢复,使用 log.Panic。
// 避免滥用 panic:虽然 panic 提供了灵活性,但过度使用可能导致代码难以维护。应尽量将 panic 限制在测试或特定边界条件处理中。
// 清理资源:如果使用 log.Fatal,确保所有必要的资源(如文件、网络连接)已经在错误发生前被正确关闭。如果使用 log.Panic,可以通过 defer 确保资源清理。
// 什么情况下要创建自定义 Logger,也就是使用 log.New 创建一个新的 Logger 实例?