Lua中协同程序coroutine与yield用法详解
Lua中协同程序coroutine与yield用法详解
孤月蓝风 发表于3个月前
Lua中协同程序coroutine与yield用法详解
  • 发表于 3个月前
  • 阅读 5
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 技术升级10大核心产品年终让利>>>   

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, 4
print("--分割线----")
print("main", coroutine.resume(co, "r")) -- true 11 -9
print("---分割线---")
print("main", coroutine.resume(co, "x", "y")) -- true 10 end
print("---分割线---")
print("main", coroutine.resume(co, "x", "y")) -- cannot resume dead coroutine
print("---分割线---")

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

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

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

第一次协同程序执行输出	1	10
foo 函数输出	2
main	true	4

之后,虽然有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"时,第二次分割线之前的输出是这样的:

第二次协同程序执行输出	r
main	true	11	-9

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

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

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

第一次协同程序执行输出	1	10
foo 函数输出	2
main	true	4
--分割线----
第二次协同程序执行输出	r
main	true	11	-9
---分割线---
第三次协同程序执行输出	x	y
main	true	10	结束协同程序
---分割线---
main	false	cannot resume dead coroutine
---分割线---

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

标签: Lua
共有 人打赏支持
粉丝 8
博文 70
码字总数 36962
×
孤月蓝风
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: