本文最后更新于:June 30, 2023 pm
本文作者:[wangwenhai] # 概要:用C模拟golang的defer->
用C模拟golang的defer
简介
众所周知,Golang有个defer语法,用来在计算之后, 返回之前干一些事情,很适合我们释放资源和善后处理等,比如下面这个文件操作:
func main(){
f,err := os.Open("demo.log")
if err != nil {
panic(err)
}
defer f.Close()
}
这让我们写代码的时候非常方便。但是C没有这个特性怎么办呢?其实可以用一定的手段来实现。
实现
Sejmp
C 库宏 int setjmp(jmp_buf environment) :创建本地的jmp_buf缓冲区并且初始化,用于将来跳转回此处。这个子程序保存程序的调用环境于env参数所指的缓冲区,env将被longjmp使用。如果是从setjmp直接调用返回,setjmp返回值为0。如果是从longjmp恢复的程序调用环境返回,setjmp返回非零值。
案例
#include <stdio.h>
#include <string.h>
#include <setjmp.h>
typedef int process(char *err);
static jmp_buf G_ENV;
static char G_ERR[20];
//--------------------------------------------
void throw(char *err)
{
strcpy(G_ERR, err);
longjmp(G_ENV, 1);
}
void defer(process *p)
{
if (setjmp(G_ENV) > 0)
{
p(G_ERR);
}
}
void http_post1()
{
throw("302: Host not found");
}
void http_post2()
{
printf("200: ok\n");
}
int defer_func(char *err)
{
printf("Catched Exceptions: %s\n", err);
return 1;
}
//
// 模拟实现 defer
//
int main()
{
defer(defer_func);
http_post1(); // 模拟异常
http_post2(); // 模拟正常
return 0;
}
我们很巧妙的使用setjmp来实现了模拟defer。其实setjmp有更多高级玩法,有待大家去发现,这里就不多赘述了。
参考
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!