最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go語言中defer使用的陷阱小結(jié)

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

01 介紹

什么是 defer

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

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

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

下面看一個例子:

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 語句的場景,很容易忘記或者由于邏輯上的錯誤導(dǎo)致資源沒有關(guān)閉。

下面的程序便是因?yàn)槭褂?return 后,關(guān)閉資源的語句沒有執(zhí)行,導(dǎo)致資源泄漏:

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()

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

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

defer 捕獲異常

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

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

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

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

實(shí)現(xiàn)代碼追蹤

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

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

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

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

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

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

在 Go 語言中,defer 一般用于資源釋放,或使用 defer 調(diào)用一個匿名函數(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
}

輸出結(jié)果:

name:phper

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

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

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

示例代碼:

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

輸出結(jié)果:

main: 100
defer: 1

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

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

03 總結(jié)

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

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

相關(guān)文章

  • golang如何設(shè)置Header Content-type

    golang如何設(shè)置Header Content-type

    這篇文章主要介紹了golang如何設(shè)置Header Content-type問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Golang設(shè)計(jì)模式之適配器模式詳細(xì)講解

    Golang設(shè)計(jì)模式之適配器模式詳細(xì)講解

    這篇文章主要介紹了使用go實(shí)現(xiàn)適配器模式,這個模式就是用來做適配的,它將不兼容的接口轉(zhuǎn)換為可兼容的接口,讓原本由于接口不兼容而不能一起工作的類可以一起工作,需要的朋友可以參考下
    2023-01-01
  • 在Go語言中使用JSON的方法

    在Go語言中使用JSON的方法

    這篇文章主要介紹了在Go語言中使用JSON的相關(guān)資料,需要的朋友可以參考下
    2018-02-02
  • Go語言語法基礎(chǔ)之算術(shù)符示例詳解

    Go語言語法基礎(chǔ)之算術(shù)符示例詳解

    這篇文章主要介紹了Go語言語法基礎(chǔ)之算術(shù)符示例詳解,詳細(xì)講解算術(shù)、關(guān)系、邏輯、位、賦值及其他運(yùn)算符的用法與示例,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-06-06
  • 深入理解Go語言設(shè)計(jì)模式之函數(shù)式選項(xiàng)模式

    深入理解Go語言設(shè)計(jì)模式之函數(shù)式選項(xiàng)模式

    在 Go 語言中,函數(shù)選項(xiàng)模式(Function Options Pattern)是一種常見且強(qiáng)大的設(shè)計(jì)模式,用于構(gòu)建可擴(kuò)展、易于使用和靈活的 API,本文就來看看它的具體用法吧
    2023-05-05
  • golang如何用http.NewRequest創(chuàng)建get和post請求

    golang如何用http.NewRequest創(chuàng)建get和post請求

    這篇文章主要介紹了golang如何用http.NewRequest創(chuàng)建get和post請求問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • Go中slog使用入門

    Go中slog使用入門

    slog是Go1.21引入的官方結(jié)構(gòu)化日志庫,本文就來介紹一下Go中slog使用入門,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2026-03-03
  • gin通過go build -tags實(shí)現(xiàn)json包切換及庫分析

    gin通過go build -tags實(shí)現(xiàn)json包切換及庫分析

    這篇文章主要為大家介紹了gin通過go build -tags實(shí)現(xiàn)json包切換及庫分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • go select編譯期的優(yōu)化處理邏輯使用場景分析

    go select編譯期的優(yōu)化處理邏輯使用場景分析

    select 是 Go 中的一個控制結(jié)構(gòu),類似于用于通信的 switch 語句。每個 case 必須是一個通信操作,要么是發(fā)送要么是接收。接下來通過本文給大家介紹go select編譯期的優(yōu)化處理邏輯使用場景分析,感興趣的朋友一起看看吧
    2021-06-06
  • Go語言通過反射實(shí)現(xiàn)獲取各種類型變量的值

    Go語言通過反射實(shí)現(xiàn)獲取各種類型變量的值

    反射是程序在運(yùn)行期間獲取變量的類型和值、或者執(zhí)行變量的方法的能力,這篇文章主要為大家講講Go語言通過反射獲取各種類型變量值的方法,需要的可以參考下
    2023-07-07

最新評論

鄯善县| 福贡县| 广宗县| 资溪县| 常山县| 大关县| 新余市| 洪泽县| 翁牛特旗| 洛川县| 卢氏县| 唐海县| 盘锦市| 大同市| 郴州市| 隆子县| 台湾省| 晋江市| 齐河县| 岑巩县| 桃园县| 且末县| 财经| 黎城县| 乌兰察布市| 通许县| 长泰县| 罗甸县| 繁昌县| 建昌县| 西林县| 平塘县| 万荣县| 彰化市| 塔河县| 阜城县| 四会市| 苏尼特左旗| 会宁县| 铜鼓县| 积石山|