【go从零单排】panic、recover、defer
🌈Don’t worry , just coding!
内耗与overthinking只会削弱你的精力,虚度你的光阴,每天迈出一小步,回头时发现已经走了很远。
📗概念
在 Go 语言中,panic 是一种用于处理异常情况的机制。它允许程序在遇到严重错误时停止执行,并可以在调用栈中向上抛出错误,直到被捕获或程序崩溃。
💻代码
panic
package main
//导入os包
import "os"
func main() {
//这行代码立即引发一个panic,并打印出信息 "a problem"。程序会在这一行停止执行,不会继续执行后面的代码。
panic("a problem")
//后面的代码都不会执行
_, err := os.Create("/tmp/file")
if err != nil {
panic(err)
}
}
//输出
//panic: a problem
//goroutine 1 [running]:
//main.main()
// /Users/dudusman/GolandProjects/awesomeProject/post.go:8 +0x25
//exit status 2
recover
使用 recover 函数来捕获 panic,从而防止程序崩溃。
recover 只能在 defer 的函数中有效。
package main
import (
"fmt"
)
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from:", r)
}
}()
fmt.Println("Starting the program...")
panic("A critical error occurred!") // 触发 panic
fmt.Println("This line will not be executed.")
}
//输出
//Starting the program...
//Recovered from: A critical error occurred!
defer
在 Go 语言中,defer 关键字用于确保在函数执行结束时执行某些操作,无论函数是正常返回还是因为发生错误而提前退出。defer 的主要用途包括资源清理(如关闭文件、解锁互斥锁等)和执行一些必要的收尾工作。
package main
import (
"fmt"
"os"
)
func main() {
//创建文件
f := createFile("/tmp/defer.txt")
//使用 defer 关键字,确保在 main 函数结束时调用 closeFile(f)。
//这意味着在 main 函数退出时,文件 f 将被关闭,无论是正常退出还是因为 panic
defer closeFile(f)
//调用 writeFile 函数,传入文件指针 f,在文件中写入数据
writeFile(f)
}
// createFile 函数接受一个字符串参数 p(文件路径),尝试创建该文件。
func createFile(p string) *os.File {
fmt.Println("creating")
f, err := os.Create(p)
if err != nil {
panic(err)
}
//如果成功,返回文件指针 f。
return f
}
func writeFile(f *os.File) {
fmt.Println("writing")
fmt.Fprintln(f, "data")
}
// closeFile 函数接受一个文件指针 f,尝试关闭文件。
func closeFile(f *os.File) {
fmt.Println("closing")
err := f.Close()
//关闭文件时发生错误,打印错误信息到标准错误输出,并使用 os.Exit(1) 退出程序
if err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
}
- defer 语句会将其后面指定的函数调用推迟到包含它的函数返回时执行
多个defer
package main
import "fmt"
func main() {
defer fmt.Println("first")
defer fmt.Println("second")
defer fmt.Println("third")
}
//输出
//third
//second
//first
🔍理解
- panic 通常用于表示程序运行时的不可恢复错误,例如数组越界、空指针解引用等。
- 当调用 panic 时,程序会停止当前的执行流程,并开始逐层返回到调用栈中的上层函数。
- 多个 defer 语句会按照后进先出(LIFO)的顺序执行。这意味着最后一个被推迟的函数会最先执行。
💡 Tips小知识点
- defer 语句的参数在声明时就会被求值,而不是在执行时。这意味着如果在 defer 语句中使用变量,其值将在 defer 被调用时确定,而不是在函数返回时。
package main
import "fmt"
func main() {
x := 10
defer fmt.Println(x) // x 的值为 10
x = 20
}
//输出10
defer用途
- 资源清理:如关闭文件、网络连接等。
- 解锁互斥锁:在并发编程中,确保在使用完共享资源后释放锁。
- 记录日志:在函数返回时记录执行情况。
💪无人扶我青云志,我自踏雪至山巅。