golang 日常開發之巧用 defer
我們都知道,在 golang 中,有一種語言特性跟 C++ 中的 RAII 特別相似,那就是 defer。例如以下兩段代碼便可實現相同的效果
#include <iostream>
class Defer {
public:
Defer() { }
~Defer() {
std::cout << "defer" << std::endl;
}
};
int main() {
Defer d;
return 0
}
import "fmt"
func main() {
defer func() {
fmt.Println("defer")
}()
}
上述兩段代碼都會在 main 函數退出時,打印出字符串 "defer"
但是 golang 中的 defer 和 c++ 中的 RAII 還是有不同之處的。在 c++ 中,RAII 作用於對象的作用域,當離開對象作用域時,便觸發 RAII 的執行,而一個函數中可能包含很多個不同的作用域。
int main() {
// 循環體內的作用域
for (size_t i=0; i<10; i++) {
Defer d; // 打印10次defer
}
// 花括號構成的作用域
{
Defer d; // 打印1次defer
}
return 0
}
而 golang 中沒有作用域的概念,它不同於 c++ 依賴程序員自行管理內存,golang 是帶 GC 的自動語言,對象的回收時機是程序員無法精確控制時機的。因此 golang 中 defer 只會在當前函數返回前才觸發執行。那麼有沒有辦法達到與 c++ 中 RAII 類似的效果呢?答案是有的,通過創建匿名函數即可。
func printDefer() {
fmt.Println("defer")
}
func main() {
for i := 0; i < 10; i++ {
func() {
defer printDefer()
}()
}
func() {
defer printDefer()
}()
}
通過上述 golang 代碼便可達到與 c++ RAII 類似的效果.
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/wofr1DKoBbJ1wlMTXiPncw