1.关键字及其用法
- defer
用于确保某些代码在函数结束前被执行。(很类似于java的finally)
//延迟执行
func example()
{
defer fmt.Println("This will be printed last.")
fmt.Println("This will be printed first.")
}
//This will be printed first.
//This will be printed last.
//fmt.Println("This will be printed last.") 被 defer 延迟执行,因此它会在 example 函数返回之前执行
//关闭文件
func readFile(filename string)
{
file, err := os.Open(filename)
if err != nil {
log.Fatal(err)
}
defer file.Close() // 确保文件在函数结束时关闭
// 读取文件内容以及后续操作...
}
//解除互斥锁
var mu sync.Mutex
var data []int
func accessData()
{
mu.Lock()
defer mu.Unlock() // 确保在访问数据后解锁
// 访问共享数据以及后续操作...
}
//记录日志
func processRequest(req Request) error {
start := time.Now()
defer func() {
log.Printf("Request took %v", time.Since(start))
}()
// 处理请求...
return nil
}
//恢复恐慌(panic):使用 defer 结合 recover 来捕获并处理恐慌,防止程序崩溃
func safeDivide(a, b int) (result int, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("division by zero: %v", r)
}
}()
result = a / b
return result, nil
}
有多个 defer 语句时,它们会按照 后进先出(LIFO) 的顺序执行
func example() {
defer fmt.Println("1")
defer fmt.Println("2")
defer fmt.Println("3")
fmt.Println("Start")
} // 输出顺序: // Start // 3 // 2 // 1
defer 语句可以在函数返回之前修改返回值
func increment() int {
x := 0
defer func() {
x++ // 这里的 x 会在函数返回时递增
}()
return x
}
// 输出:0
//x 是一个局部变量,初始值为 0。
//defer 语句会在函数返回之前执行,因此 x++ 会在 return x 之后、函数真正返回之前执行。
//在 return x 时,x 的值是 0。Go 语言会将 x 的当前值(即 0)复制到返回值中,并准备返回。
//defer 语句中的 x++ 会在 return 语句之后执行,但此时 x 已经被复制到返回值中,x++ 只会修改局部变量 x 的值,而不会影响已经确定的返回值。
//最终输出:函数返回的值是 0,因此 fmt.Println(increment()) 输出 0。
func increment() (x int) {
defer func() {
x++ // 这里的 x 会在函数返回时递增
}()
return 0
}
// 输出:1
//x 是一个 命名返回值,初始值为 0(因为 Go 语言中整数类型的默认值是 0)。
//defer 语句会在函数返回之前执行,因此 x++ 会在 return 0 之后、函数真正返回之前执行。
在 return 0 时,x 的值被设置为 0,但此时 x 是一个命名返回值,Go 语言会记住这个值,并准备返回。
defer 语句中的 x++ 在 return 0 之后执行,x 被递增为 1。
最终输出:由于 x 是命名返回值,defer 语句中的 x++ 修改了 x 的值,因此函数返回的值是 1,而不是 0。