当前位置:首页 > 域名

Golang 语言中的 Defer 怎么使用?

 01介绍

在 Golang 语言中,语言用我们可以在函数(自定义和部分内置)或方法中使用 defer 关键字注册延迟调用(一个或多个),语言用多个延迟调用的语言用执行顺序是先进后出(FILO)。并且不会受到函数执行结束退出,语言用显式调用 return 和主动(或被动)触发 panic 的语言用影响,注册成功的语言用所有延迟调用都会被执行,除非 defer 注册在 return 之后或者函数(或方法)调用 os.Exit(1)。语言用

defer 注册多个延迟调用,语言用执行顺序是语言用先进后出(FILO)。

示例代码:

func main () {   defer func() {    fmt.Println("A")  }()  defer func() {    fmt.Println("B")  }()  fmt.Println("main goroutine run over")  // panic("this is a panic example")  // return } 

defer 如果定义在 return 之后,语言用它等于 defer 没有注册,语言用将不会执行。语言用

示例代码:

func main () {   fmt.Println("main")  return  defer func() {    fmt.Println("A")  }() } 

defer 所在的语言用函数或方法中,如果调用 os.Exit(1),语言用defer 即便注册,语言用也不会执行。

示例代码:

func main () {   defer func() {    fmt.Println("A")  }()  fmt.Println("main")  os.Exit(1) } 

defer 必须在函数和方法中才可以使用,并且 defer 后面必须是函数(自定义和部分内置函数)或方法,defer 函数的实参是值拷贝。

示例代码

func main () {   a := 0  defer func(num int) {    fmt.Println("defer func()", num)  }(a)  a++  fmt.Println(a) } 

02使用场景

使用关键字 defer 注册的高防服务器函数(自定义和部分内置)或方法,因为不会受到函数执行结束,显式调用 return 和主动(或被动)触发 panic 的影响,通常会用于防止忘记释放资源和捕获 panic(同一 goroutine 中) 防止应用程序崩溃退出的应用场景。

示例代码:

func main () {   f, err := os.OpenFile("text.txt", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0755)  if err != nil {    fmt.Println(err)  }  defer f.Close()  n, err := f.WriteString("this is a text file\t")  if err != nil {    fmt.Println(err)  }  fmt.Println(n) } 

阅读上面这段代码,我们使用 defer 延迟调用释放资源,防止忘记释放资源(关闭文件或解锁),通常 defer 会放在错误检查之后。

示例代码:

func main () {   defer func() {    if err := recover(); err != nil {     fmt.Println("this is a panic" )   }  }()  panic("this is a test panic")  fmt.Println("main") } 

阅读上面这段代码,我们使用 defer 配合 recover 函数,用于拦截 panic(同一 goroutine 中),防止程序崩溃退出。

03注意事项

虽然使用 defer 具有可以用于防止忘记释放资源和拦截 panic(同一 goroutine 中)防止应用程序崩溃退出等好处。

但是 defer 也有副作用,它会使资源延迟释放,defer 尽量不要再 for-loop 中使用,并且相比于未使用 defer 调用的函数(自定义和部分内置)或方法,defer 也有一定的性能损耗,Golang 语言官方也在 golang 1.13 和 golang 1.14 中优化了 defer 的性能。

相比于 defer 的性能损耗,defer 带来的云服务器使代码更加优雅、可读和健壮等优势,我认为 defer 综合来看,利大于弊,它可以给 gopher 们带来的收益比付出的代价更大。所以,我建议大家尽量使用 defer。

还有一点需要注意的是,我们不要使用 defer 调用有返回值的自定义函数或方法,返回值会丢失,可能会给应用程序带来意想不到的错误。

04总结

本文我们介绍了 defer 的执行机制,使用场景和注意事项,并且给出了相应的示例代码。通常我们会在 Golang 语言开发中使用 defer 防止忘记释放资源(关闭文件或解锁)和捕获 panic(同一 goroutine 中) 防止应用程序崩溃退出。

本文转载自微信公众号「Golang语言开发栈」,可以通过以下二维码关注。转载本文请联系Golang语言开发栈公众号。

分享到:

滇ICP备2023006006号-16