欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go語言中defer使用的陷阱小結

 更新時間:2024年01月21日 15:48:36   作者:FrankGopher  
本文主要介紹了Go語言中defer使用的陷阱小結,分別是defer語句不可以在return語句之后,defer語句執(zhí)行的匿名函數(shù),匿名函數(shù)的參數(shù)會被預先處理,具有一定的參考價值,感興趣的可以了解一下

01 介紹

什么是 defer

defer 是Go語言提供的一種用于注冊延遲調用的機制,以用來保證一些資源被回收和釋放。

defer 注冊的延遲調用可以在當前函數(shù)執(zhí)行完畢后執(zhí)行(包括通過return正常結束或者panic導致的異常結束)

當defe注冊了的函數(shù)或表達式逆序執(zhí)行,先注冊的后執(zhí)行,類似于棧 ”先進后出“

下面看一個例子:

package main

import "fmt"

func main() {
   f()
}

func f() {
   defer func() {
      fmt.Println(1)
   }()
   defer func() {
      fmt.Println(2)
   }()
   defer func() {
      fmt.Println(3)
   }()
}

輸出:

3
2
1

如何使用defer

釋放資源

使用 defer 可以在一定程度上避免資源泄漏,尤其是有很多 return 語句的場景,很容易忘記或者由于邏輯上的錯誤導致資源沒有關閉。

下面的程序便是因為使用 return 后,關閉資源的語句沒有執(zhí)行,導致資源泄漏:

f, err := os.Open("test.txt")
if err != nil {
   return
}
f.process()
f.Close()

此處更好的做法如下:

f, err := os.Open("test.txt")
if err != nil {
   return
}
defer f.Close()

// 對文件進行操作
f,process()

此處當程序順利執(zhí)行后,defer 會釋放資源;defer 需要先注冊后使用,比如此處,打開文件異常時,程序執(zhí)行到 return 語句時便會退出當前函數(shù),沒有經過 defer,所以此處defer 不會執(zhí)行

defer 捕獲異常

在 go 中沒有 try 和 catch , 當程序出現(xiàn)異常是,我們需要從異常中恢復。我們這時可以利用 defer + recover 進行異常捕獲

func f() {
    defer func() {
       if err := recover(); err != nil {
          fmt.Println(err)
       }
    }()
    // do something
    panic("panic")
}

注意,recover() 函數(shù)在在defer中用匿名函數(shù)調用才有效,以下程序不能進行異常捕獲:

func f() {
    if err := recover(); err != nil {
        fmt.Println(err)
    }
    //  do something
    panic("panic")
}

實現(xiàn)代碼追蹤

下面提供一個方法能追蹤到程序時進入或離開某個函數(shù)的信息,此處可以用來測試特定函數(shù)有沒有被執(zhí)行

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

記錄函數(shù)的參數(shù)與返回值

有時候程序返回結果不符合預期是, 大家可能手動打印 log 調試,此時使用 defer 記錄函數(shù)的參數(shù)和返回值,避免手動多處打印調試語句

func func1(s string) (n int, err error) {
    defer func() {
        log.Printf("func1(%q) = %d, %v", s, n, err)
    }()
    return 7, nil
}

實現(xiàn)代碼追蹤 和 記錄函數(shù)的參數(shù)與返回值 

在 Go 語言中,defer 一般用于資源釋放,或使用 defer 調用一個匿名函數(shù),在匿名函數(shù)中使用 recover() 處理異常 panic。

在使用 defer 時,也很容易遇到陷阱,本文我們介紹使用 defer 時有哪些陷阱。

02 defer 陷阱

defer 語句不可以在 return 語句之后。

示例代碼:

func main() {
    name := GetUserName("phper")
    fmt.Printf("name:%s\n", name)
    if name != "gopher" {
        return
    }
    defer fmt.Println("this is a defer call")
}

func GetUserName(name string) string {
    return name
}

輸出結果:

name:phper

閱讀上面這段代碼,我們在 return 語句之后執(zhí)行 defer 語句,通過輸出結果可以發(fā)現(xiàn) defer 語句調用未執(zhí)行。

雖然 defer 可以在函數(shù)體中的任意位置,我們也是需要特別注意使用 defer 的位置是否可以執(zhí)行。

defer 語句執(zhí)行匿名函數(shù),參數(shù)預處理。

示例代碼:

func main() {
    var count int64
    defer func(data int64) {
        fmt.Println("defer:", data)
    }(count + 1)
    count = 100
    fmt.Println("main:", count)
}

輸出結果:

main: 100
defer: 1

閱讀上面這段代碼,首先我們定義一個類型為 int64 的變量 count,然后使用 defer 語句執(zhí)行一個匿名函數(shù),匿名函數(shù)傳遞參數(shù)為 count + 1,最終 main 函數(shù)輸出 100,defer 執(zhí)行的匿名函數(shù)輸出 1。

因為在執(zhí)行 defer 語句時,執(zhí)行了 count + 1,并先將其存儲,等到 defer 所在的函數(shù)體 main 執(zhí)行完,再執(zhí)行 defer 語句調用的匿名函數(shù)的函數(shù)體中的代碼。

03 總結

本文主要介紹在使用 defer 語句時可能會遇到的陷阱。分別是 defer 語句不可以在 return 語句之后;defer 語句執(zhí)行的匿名函數(shù),匿名函數(shù)的參數(shù)會被預先處理。

到此這篇關于Go語言中defer使用的陷阱小結的文章就介紹到這了,更多相關Go語言 defer使用內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • golang 實現(xiàn)并發(fā)求和

    golang 實現(xiàn)并發(fā)求和

    這篇文章主要介紹了golang 并發(fā)求和的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05
  • Golang中map的深入探究

    Golang中map的深入探究

    Go中Map是一個KV對集合,下面這篇文章主要給大家介紹了關于Golang中map探究的相關資料,文中通過實例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2022-09-09
  • Go語言中的復合類型詳細介紹

    Go語言中的復合類型詳細介紹

    這篇文章主要介紹了Go語言中的復合類型詳細介紹,復合類型包括:結構體、數(shù)組、切片、Maps,需要的朋友可以參考下
    2014-10-10
  • Go語言interface 與 nil 的比較

    Go語言interface 與 nil 的比較

    在golang中,nil只能賦值給指針、channel、func、interface、map或slice類型的變量。如果未遵循這個規(guī)則,則會引發(fā)panic。
    2017-08-08
  • 6行代碼快速解決golang TCP粘包問題

    6行代碼快速解決golang TCP粘包問題

    在用golang開發(fā)人工客服系統(tǒng)的時候碰到了粘包問題,那么什么是粘包呢?下面這篇文章主要給大家介紹了關于如何通過6行代碼快速解決golang TCP粘包問題的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒下面隨著小編來一起學習學習吧。
    2018-03-03
  • golang 設置web請求狀態(tài)碼操作

    golang 設置web請求狀態(tài)碼操作

    這篇文章主要介紹了golang 設置web請求狀態(tài)碼操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Golang基礎教程之字符串string實例詳解

    Golang基礎教程之字符串string實例詳解

    這篇文章主要給大家介紹了關于Golang基礎教程之字符串string的相關資料,需要的朋友可以參考下
    2022-07-07
  • 如何使用Go語言實現(xiàn)遠程執(zhí)行命令

    如何使用Go語言實現(xiàn)遠程執(zhí)行命令

    遠程執(zhí)行命令最常用的方法就是利用SSH協(xié)議,將命令發(fā)送到遠程機器上執(zhí)行,并獲取返回結果。本文將介紹如何使用Go語言實現(xiàn)遠程執(zhí)行命令。下面一起來看看。
    2016-08-08
  • 深入了解Golang中reflect反射的使用

    深入了解Golang中reflect反射的使用

    這篇文章主要介紹了深入了解Golang中reflect反射的使用,Go語言中的反射是一種機制,可以在運行時動態(tài)地獲取類型信息和操作對象,以及調用對象的方法和屬性等,需要詳細了解可以參考下文
    2023-05-05
  • golang獲取用戶輸入的幾種方式

    golang獲取用戶輸入的幾種方式

    這篇文章給大家介紹了golang獲取用戶輸入的幾種方式,文中通過代碼示例給大家講解的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友跟著小編一起來學習吧
    2024-01-01

最新評論