更多精彩内容,请关注微信公众号:后端技术小屋

我们都知道,在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类似的效果.

推荐阅读

更多精彩内容,请扫码关注微信公众号:后端技术小屋。如果觉得文章对你有帮助的话,请多多分享、转发、在看。
二维码