Lua中协同程序coroutine与yield用法详解

Lua中协同程序coroutine与yield用法详解

Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。

而现在很多地方都会用到Lua语言,例如魔兽插件、剑网三插件、各种其他程序扩展、热更新等,所以这几天正在学习一下Lua语言,做技术储备。

而在Lua的学习过程中,大部分都很容易理解,唯独协同程序Coroutine一直理解不了。于是上网查了很多人的解释,加上测试,最终明白了其用法,分享出来,与大家交流。

本文只解释一下遇到的问题,所以你需要看过基本的Lua语法,了解基本的协程运作方式。

首先看下面的代码:

function foo (a)    print("foo 函数输出", a)    return coroutine.yield(2 * a) -- 返回  2*a 的值end co = coroutine.create(function (a , b)    print("第一次协同程序执行输出", a, b) -- co-body 1 10    local r = foo(a + 1)         print("第二次协同程序执行输出", r)    local r, s = coroutine.yield(a + b, a - b)  -- a,b的值为第一次调用协同程序时传入         print("第三次协同程序执行输出", r, s)    return b, "结束协同程序"                   -- b的值为第二次调用协同程序时传入end)        print("main", coroutine.resume(co, 1, 10)) -- true, 4print("--分割线----")print("main", coroutine.resume(co, "r")) -- true 11 -9print("---分割线---")print("main", coroutine.resume(co, "x", "y")) -- true 10 endprint("---分割线---")print("main", coroutine.resume(co, "x", "y")) -- cannot resume dead coroutineprint("---分割线---")

在协程coroutine中,当调用coroutine.yield方法时,协程coroutine会挂起,当下一次调用coroutine时会从yeild的地方继续执行。而其中让我摸不着头脑的地方,便是resume时和yield时的参数传递了。

如果coroutine.create里的函数有参数的话,那么第一次在resume中传递的参数,便是给create中函数传递的参数。

之后会执行到return coroutine.yield(2 * a),这时需要注意:协程coroutine被挂起,print会输出协程coroutine的执行结果,而且会输出coroutine.yield(2 * a)的结果。所以第一次分割线之前的输出是这样的:

第一次协同程序执行输出110foo 函数输出2maintrue4

之后,虽然有local r = foo(a + 1),但foo函数中的return并没有将coroutine.yield中的参数(或者说返回给resume的执行结果)返回,所以2 * a并没有赋值给r。而赋值给r的其实是第二次调用resume时传递的参数。

在第二次调用resume时,除了co还传递了一个字符串参数"r",而这个参数将会成为foo函数的返回值,并被赋值给r。resume时可以传递多个参数进去,但之前的yield中只有一个参数,其余的参数会被忽略。如果在resume时不传递参数,而yield中有参数,那么返回值则为nil,则r为nil。在这一次的yield中有两个参数,a+b和a-b,a和b是第一次调用时传递进来的参数,所以会返回他们计算的结果。

当传递参数为"r"时,第二次分割线之前的输出是这样的:

第二次协同程序执行输出rmaintrue11-9

搞懂了这两次的输出,后面的也就不难理解了。

当创建协程coroutine时,默认会挂起,只有在调用resume时才会被执行,当yield时会被再次挂起。第一次传递的参数会被传入create的函数中,而之后的参数传递,都是传递给yield的。并且yield中的参数会加入到resume的返回结果。

上面代码的所有输出如下:

第一次协同程序执行输出110foo 函数输出2maintrue4--分割线----第二次协同程序执行输出rmaintrue11-9---分割线---第三次协同程序执行输出xymaintrue10结束协同程序---分割线---mainfalsecannot resume dead coroutine---分割线---

以上分享为个人理解,如有错误欢迎指正。希望对大家有所帮助。

推荐阅读

    学习写字楼新选择6000元主流配置

    学习写字楼新选择6000元主流配置,,这种配置需要考虑双核心的办公和娱乐平台,充分考虑办公室的办公需求和娱乐需求,以约6000元的预算和cost-e

    opporeno8参数配置及价格

    opporeno8参数配置及价格,面部,亿元,Oppo的荣誉2020年1月4日,接近屏幕关闭传感器是否支持双卡:支持oppor11splus什么时候上市的Oppo R11S P

    魅蓝note6性能参数有哪些

    魅蓝note6性能参数有哪些,摄像头,蓝牙,魅蓝note6性能参数有哪些魅力蓝色Note6最好拍照。电池寿命更长。蓝色Note6使用高通 snapdragon 625

    Lucene学习之高亮显示

    Lucene学习之高亮显示,索引,字符,在搜索引擎中我们经常会看到这样的情景: 红色部分我们称之为高亮显示,lucene提供了HighLighter模块来实

    设置总账参数|用友u8设置总账参数

    设置总账参数|用友u8设置总账参数,,1. 用友u8设置总账参数1、首先要点开数据权限控制设置;2、选择想要设置控制的单据;3、打开后看到左上角

    探探语言设置|探探怎么设置语言

    探探语言设置|探探怎么设置语言,,1. 探探怎么设置语言打开探探软件,然后就有消息提示的红点,点开就行了!其实这些软件都是挺简单的操作的,都是

    csgo参数设置|csgo怎么保存

    csgo参数设置|csgo怎么保存,,csgo怎么保存第一步下载csgo的官方版本。然后再下载一个5e对战平台,PS:5e的账号和csgo的账号不是一个账号。第

    移动apn设置|移动apn设置参数

    移动apn设置|移动apn设置参数,,移动apn设置参数1、打开手机系统设置界面应用,点击页面中的“移动网络”设置选项。2、进入移动网络设置页面

    git设置编码|git语言设置

    git设置编码|git语言设置,,git设置编码点击cap4j搜索从git直接链接上拉代码。git语言设置Git是一个开源的分布式版本控制系统,可以有效、高