使用 Lua 协程模拟 Golang 的 go defer 编程模式

封装 go 函数

在 使用 Lua 协程处理异步回调函数 中已经介绍

这里简要列下:

  1. 封装 go 函数
    ---go 函数创建并启动一个协程
    ---@param _co_task function @函数原型 fun(_co:thread)
    function go(_co_task)
        local co = coroutine.create(_co_task) -- 创建的协程是暂停的
        coroutine.resume(co, co)              -- 调用 coroutine.resume 激活协程执行
    end
    
  2. 封装项目中异步函数
    ---封装 c_model.c_foo 异步函数,成为协程函数
    ---@param _co thread @协程对象
    ---@return boolean,string
    function co_foo(_co)
        c_model.c_foo(function(_ok, _result)
            coroutine.resume(_co, _ok, _result) -- 2. 回调函数被调用后,激活本协程继续执行。并把_ok, _result传递给 yield
        end)
        return coroutine.yield()                -- 1. 主动放弃运行,本协程被切换出去
    end
    
  3. 使用例子
    ---test顺序编写代码,解决回调函数造成同块逻辑被撕裂的例子
    ---@param _co thread @协程对象
    function test(_co)
        for i = 1, 10, 1 do
            local ok, result = co_foo(_co) -- co_foo 会先 yield 切出;内部回调被执行时, resume 重新切回来继续执行
            print(ok, result)
        end
    end
    
    -- 启动 test 协程
    go(test)
    

封装 defer

defer 的特点有以下:

  • 协程正常退出能被执行
  • 协程异常退出能被执行
  • 同个协程内可以多次调用 defer
  • defer 被执行时,按出栈顺序被执行
defer 多次执行

首先定义 defer 函数,让它具备能多次被调用:

function defer(_co_wrap, h)
    table.insert(_co_wrap.defer_handlers, h)
end

因为要对 defer 的函数句柄做保持,以便退出时执行。包裹了下 co 对象:

---@class co_wrap
---@field co thread
---@field defer_handlers fun(_co_error:co_error)[]

同时定义下让 defer 的函数知道是否有错误的对象:

---@class co_error
---@field ok boolean
defer 被执行时,按出栈顺序被执行
function invoke_defer_handlers(_co_wrap, _co_error)
    for i=#_co_wrap.defer_handlers, 1, -1 do
        local h = _co_wrap.defer_handlers[i]
        xpcall(h, function(err) print(err) end, _co_error)
    end
end
协程异常时,能被执行

Lua 协程异常,通过 coroutine.resume 捕获,并返回错误信息

因此主要封装下 coroutine.resume :

function coroutine_resume(_co_wrap, ...)
    local ok, errmsg = coroutine.resume(_co_wrap.co, ...)
    if not ok then
        invoke_defer_handlers(_co_wrap, {ok=false}) -- 异常退出
    end
end
协程正常退出时,能被执行
function go(_co_task)
	local co = coroutine.create(function(_co_wrap)
        _co_task(_co_wrap)
        invoke_defer_handlers(_co_wrap, {ok=true}) -- 正常退出
    end)
    local cowrap = { co = co, defer_handlers = {} } ---@type co_wrap
    coroutine_resume(cowrap, cowrap) -- 初创建的协程是暂停的,手动触发执行
end

以上就可以在 Lua 中完全 Golang 的方式编写协程代码了

协程间通信

由于项目中暂时是一根线程管理一个 lua_state 对象,因此暂时无需求多线程中的协程间的通信需求

待续

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/586154.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Nginx配置Https缺少SSL模块

1、Linux下Nginx配置https nginx下载和安装此处就忽略,可自行百度 1.1、配置https 打开nginx配置文件 vim /opt/app/nginx/conf/nginx.conf相关https配置 server {listen 443 ssl; #开放端口server_name echarts.net;#域名#redirect to https#ssl on; #旧版#ssl证…

ubuntu 利用阿里网盘API实现文件的上传和下载

文章目录 背景脚本初始化 阿里云盘API工具 aligo安装aligoaligo教程实战parse.py 演示上传文件上传文件夹下载文件下载文件夹 背景 最近在用ubuntu系统做实验,而ubuntu 系统的文件上传和下载操作很麻烦; 于是便打算使用阿里网盘的API 进行文件下载与上传…

VitePress 构建的博客如何部署到 Netlify 平台?

VitePress 构建的博客如何部署到 Netlify 平台? 前言 之前写了篇文章【使用 Vitepress 构建博客并部署到 github 平台】,有个老哥说 github page 访问太慢了,希望放到 Netlify 平台上面。 咱也没部署过,就试了一下,发…

JAVA面试专题-Redis

你在最近的项目中哪些场景使用了Redis 缓存 缓存穿透 缓存穿透:查询一个不存在的数据,mysql查询不到数据也不好直接写入缓存,导致每次请求都查数据库。 解决方案一:缓存空数据,即使查询返回的数据为空,也把…

C#应用程序实现多屏显示

前言 随着业务发展,应用程序在一些特定场景下,只在一个显示器上展示信息已经不能满足用户需求。我们如何把主屏运行程序中多个窗体移动到各个扩展屏幕位置显示呢?C# 是通过什么方式来实现的,下面介绍 C# 使用 Screen 类的方式来实…

vue+elementUI实现点击左右箭头切换按钮功能

原本是可以用el-tabs做的,就像下面的样式,但是领导说不行 最后用button和element里面的el-carousel(走马灯)结合了一下 长这样 感觉还不错 可以自己改样式 代码如下: <div class"drawer-carousel"><el-carousel arrow"always" :loop"false…

Linux基础part-5

1、Linux用户与用户组管理 1、用户是什么&#xff1f; 实现资源分派&#xff08;区分和管理系统资源的访问权限&#xff0c;将不同的资源分配给不同的用户&#xff09;实现认证pam和授权&#xff08;用户身份通常通过用户名和密码进行认证&#xff0c;认证成功后系统将授予用…

开源、轻量、易用的服务器实时监控工具:哪吒探针

本文首发于只抄博客&#xff0c;欢迎点击原文链接了解更多内容。 前言 哪吒探针是一个开源、轻量、易用的服务器监控、运维工具&#xff0c;它有以下几个特点&#xff1a; 一键安装&#xff1a;可以一键安装面板与 Agent&#xff0c;并且支持 Linux、Windows、MacOS、OpenWRT…

scikit-learn:Python中的机器学习-1

简介&#xff1a;问题设置 什么是机器学习&#xff1f; 机器学习是关于构建具有可调参数的程序&#xff0c;这些参数可以自动调整&#xff0c;以便通过适应先前看到的数据来改善其行为。机器学习可以被认为是人工智能的一个子领域&#xff0c;因为这些算法可以被视为构建模块…

气象数据nc数据矢量化处理解析及可视化

气象数据可视化是将气象学领域中复杂的数据集转化为图形或图像的过程&#xff0c;以直观展示天气现象、气候模式、趋势和预报结果。气象数据的可视化技术广泛应用于科学研究、气象预报、航空、航海、农业生产、灾害预警系统、城市规划、公众服务等领域。以下是一些关键的气象数…

CSAPP | Bits, Bytes, and Integers

Great Reality Ints are not Integers, Floats are not Reals 对于 (x y) z x (y z)&#xff0c;无符号整形和有符号整形是成立的。 但是对于浮点数, (1e20 -1e20) 3.14 -> 3.14&#xff0c;而 1.e20 (-1e20 3.14) 0 typedef struct {int a[2];double d; }stru…

【LeetCode】拓扑排序——课程表 I II

拓扑排序&#xff1a; AOV网&#xff1a;若用DAG图&#xff08;有向无环图&#xff09;表示一个工程&#xff0c;其顶点表示活动&#xff0c;用有向边<Vi, Vj>表示活动Vi必须先于活动Vj进行的这样一种关系&#xff0c;则将这种有向图称为顶点表示活动的网络&#xff0c;…

JSP:操作指令

目录 目录 一、jsp:useBean操作 语法格式&#xff1a; 属性说明&#xff1a; scope作用域&#xff1a; 1.page&#xff1a; 2.request&#xff1a; 3.session&#xff1a; 4.application 案例&#xff1a;JavaBean的简单使用 二、jsp:setProperty操作 语法格式&a…

【记录】Python3| 将 PDF 转换成 HTML/XML(✅⭐⭐⭐⭐pdf2htmlEX)

本文将会被汇总至 【记录】Python3&#xff5c;2024年 PDF 转 XML 或 HTML 的第三方库的使用方式、测评过程以及对比结果&#xff08;汇总&#xff09;&#xff0c;更多其他工具请访问该文章查看。 文章目录 pdf2htmlEX 使用体验与评估1 安装指南2 测试代码3 测试结果3.1 转 HT…

jenkins转载文本

基于Docker容器DevOps应用方案 企业业务代码发布系统 一、企业业务代码发布方式 1.1 传统方式 以物理机或虚拟机为颗粒度部署部署环境比较复杂&#xff0c;需要有先进的自动化运维手段出现问题后重新部署成本大&#xff0c;一般采用集群方式部署部署后以静态方式展现 1.2 容…

ubuntu部署sonar与windows下使用sonar-scanner

ubuntu部署sonar与windows下使用sonar-scanner sonar部署java安装mysql安装配置sonarqube 插件安装sonar-scanner使用简单使用 sonar部署 使用的是sonarqube-7.5&#xff0c;支持的java环境是jdk8&#xff0c;且MySQL版本 >5.6 && <8.0 java安装 打开终端&…

为什么3D模型材质是透明的?---模大狮模型网

在进行3D建模和渲染过程中&#xff0c;正确的材质设置是保证模型外观逼真和渲染效果良好的关键之一。然而&#xff0c;有时您可能会遇到3D模型材质变成透明的情况&#xff0c;这可能会导致意想不到的效果和渲染结果。本文将探讨一些可能导致3D模型材质变成透明的原因&#xff0…

Go中为什么不建议用锁?

Go语言中是不建议用锁&#xff0c;而是用通道Channel来代替(不要通过共享内存来通信&#xff0c;而通过通信来共享内存)&#xff0c;当然锁也是可以用&#xff0c;锁是防止同一时刻多个goroutine操作同一个资源&#xff1b; GO语言中&#xff0c;要传递某个数据给另一个gorout…

亚马逊关键字搜索商品列表API接口:探索海量商品的利器

亚马逊关键字搜索商品列表API接口允许开发者通过输入关键字或特定参数&#xff0c;在亚马逊平台上进行商品搜索&#xff0c;并返回符合搜索条件的商品列表信息。这些信息包括商品的标题、图片、价格、评价等&#xff0c;为商家、开发者以及市场分析师提供了丰富的商品数据支持。…

Aker(安碁科技)晶振产品应用和选型

一、石英晶体振荡器简介 在电子电路系统中&#xff0c;特定的动作需要严格按照一定的顺序进行&#xff0c;以确保数据被正确处理和操作&#xff0c;时钟信号就成了系统工作的重要引导者。而且在多模块复杂电路系统中&#xff0c;为了确保不同功能模块能协调一致地工作&#xf…
最新文章