当前位置: 代码迷 >> 综合 >> defer 和追踪
  详细解决方案

defer 和追踪

热度:78   发布时间:2023-10-20 07:46:29.0

关键字简介

关键字 defer 允许我们推迟到函数返回之前(或任意位置执行 return 语句之后)一刻才执行某个语句或函数(为什么要在返回之后才执行这些语句?因为 return 语句同样可以包含一些操作,而不是单纯地返回某个值)。
关键字 defer 的用法类似于面向对象编程语言 Java 和 C# 的 finally 语句块,它一般用于释放某些已分配的资源

eg

package main
import "fmt"func main() {function1()
}func function1() {fmt.Printf("In function1 at the top\n")defer function2()fmt.Printf("In function1 at the bottom!\n")
}func function2() {fmt.Printf("function2: Deferred until the end of the calling function!")
}

输出:

In Function1 at the top
In Function1 at the bottom!
Function2: Deferred until the end of the calling function!

请将 defer 关键字去掉并对比输出结果。

defer接受参数

下面这个例子就会在执行 defer 语句时打印 0:

func a() {i := 0defer fmt.Println(i)i++return }

当有多个 defer 行为被注册时,它们会以逆序执行(类似栈,即后进先出):

func f() {for i := 0; i < 5; i++ {defer fmt.Printf("%d ", i)}
}

上面的代码将会输出:4 3 2 1 0。

defer追踪

一个基础但十分实用的实现代码执行追踪的方案就是在进入和离开某个函数打印相关的消息,即可以提炼为下面两个函数:

func trace(s string) { fmt.Println("entering:", s) }
func untrace(s string) { fmt.Println("leaving:", s) }

以下代码展示了何时调用两个函数:

package mainimport "fmt"func trace(s string)   { fmt.Println("entering:", s) }
func untrace(s string) { fmt.Println("leaving:", s) }func a() {trace("a")defer untrace("a")fmt.Println("in a")
}func b() {trace("b")defer untrace("b")fmt.Println("in b")a()
}func main() {b()
}

结果

entering: b
in b
entering: a
in a
leaving: a
leaving: b

使用 defer 语句来记录函数的参数与返回值

package mainimport ("io""log"
)func func1(s string) (n int, err error) {defer func() {log.Printf("func1(%q) = %d, %v", s, n, err)}()return 7, io.EOF
}func main() {func1("Go")
}

输出:

Output: 2011/10/04 10:46:11 func1("Go") = 7, EOF

转载地址

https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/06.4.md