golang:defer语句

  defer語句將函數調用壓到棧中,函數調用的順序遵循Last In First Out的原則。棧中的函數將在調用函數返回之後被執行。defer通常用在簡單的函數來執行清理工作。
Example:
func CopyFile(dstName, srcName string) (written int64, err error) {
    src, err := os.Open(srcName)
    if err != nil {
        return
    }

    dst, err := os.Create(dstName)
    if err != nil {
        return
    }

    written, err = io.Copy(dst, src)
    dst.Close()
    src.Close()
    return
}
上述的代碼中存在一個bug,如果在os.Create()函數執行失敗後,打開的文件將不能關閉,所以補救的措施就是在os.Create()函數創建失敗return的時候,執行src.Close()語句。但是問題來了,如果函數很複雜以至於問題不能被輕易的發現怎麼辦,所以這裡使用defer語句就可以方便解決這個問題。
改寫後的代碼如下:
func CopyFile(dstName, srcName string) (written int64, err error) {
    src, err := os.Open(srcName)
    if err != nil {
        return
    }
    defer src.Close()

    dst, err := os.Create(dstName)
    if err != nil {
        return
    }
    defer dst.Close()

    return io.Copy(dst, src)
}
defer語句的行為是簡單直觀,並且可預測。關於defer有下面三條簡單的規則:
  1. defer語句給定的時候,defer函數的參數也是給定的
// 該函數打印的值為0
func a() {
    i := 0
    defer fmt.Println(i)
    i++
    return
}
  1. defer函數調用在調用函數返回之後按照LIFO的順序被執行
// 該函數將打印"3210"
func b() {
    for i := 0; i < 4; i++ {
        defer fmt.Print(i)
    }
}
  1. defer函數可能對函數返回值進行重新讀取和賦值
// 該函數的返回值為2
func c() (i int) {
    defer func() { i++ }()
    return 1
}
這對於修改函數的錯誤返回值是很方便的。
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容