相关文章推荐
风流倜傥的松鼠  ·  react-native-fs ...·  1 年前    · 
文雅的移动电源  ·  jQuery延迟函数 ...·  1 年前    · 
傻傻的伤痕  ·  如何实现C# ...·  1 年前    · 

协程执行也有返回值,并且每次执行结束或暂停都有返回值,每次继续都有不同的入参

3.1 执行结束返回值

一个协程正常执行结束,如果不指定 return ,那么默认会返回一个 true

-- 协程执行结束返回值
cor4 = coroutine.create(
        function()
                print("结束啦")
-- 接收返回值
ret4 = coroutine.resume(cor4)
print(ret4)

运行结果:

3.2 暂停返回值

上面使用协程暂停和继续时,我们知道了,每次在定义协程的 function 中调用 yield ,都必须再次调用 resume 才能继续执行协程,而接收协程返回值的方法就是 resume ,所以猜想每次 yield ,都会有返回值,下面就来测试下

打印两次执行协程的返回值:

-- 协程暂停返回值
cor5 = coroutine.create(
        function(a)
                print('接收参数:',a)
                -- 暂停协程
                coroutine.yield()
print(coroutine.resume(cor5,10))
print(coroutine.resume(cor5,10))

运行结果:

print('运行时状态:',coroutine.status(cor6)) coroutine.yield() print('恢复运行时状态:',coroutine.status(cor6)) print('运行前状态:',coroutine.status(cor6)) coroutine.resume(cor6) print('暂停后状态:',coroutine.status(cor6)) coroutine.resume(cor6) print('运行完成后状态:',coroutine.status(cor6))

运行结果:

所以上面我们称为暂停协程是不确切的,应该称为挂起,可以看到协程有三种状态: 挂起、运行、死亡

5. 协程实现生产者消费者模式

协程可以被挂起和继续,那么实现生产者和消费者就简单多了,消费者执行生产者协程生产,生产者协程生产完成后,将自身挂起,将产品作为返回值返回,消费者进行消费即可

produce = coroutine.create(
        function()
                local i = 0
                while(i < 10) do
                        i = i + 1
                        print('生产者生产:',i)
                        -- 挂起协程
                        coroutine.yield(i)
function consumer()
        while(true) do
                -- 执行协程
                ok,ret = coroutine.resume(produce)
                if ok and ret ~= nil then
                        print('消费者消费:',ret)
                        break
-- 开始程序
consumer()

运行结果:

如果不处理异常,那么程序将会退出,处理异常有两种方式

3.1 pcall

pcall 可以测试函数的执行,第一个参数为函数名,后面参数为入参,如果没有异常,那么返回 true 和函数返回值,否则返回 false 和异常:

-- error
function requireNumber(a)
        if type(a) ~= type(1) then
                error("必须是number类型")
        return a
-- requireNumber('zhangsan')
-- pcall
print(pcall(requireNumber,1))
print(pcall(requireNumber,'1'))

运行结果:

xpcall 可以处理异常,只允许两个参数,第一个为调用的函数名,第二个为处理异常的 function

-- xpcall
function handleException(err)
        print('出现异常:',err)
function throwException()
        error('有个异常')
xpcall(throwException,handleException)

运行结果:

2. 面向对象

如何让上面的 user 成为一个类型,被其他变量使用呢?
答案是结合 : 和使用元表,在 function table名.函数名 方式时,将 . 替换成 : ,就可以在函数内部使用 self 来获取自身,此时使用元表的 __index ,将 self 和一张空表结合,返回出去,就能得到一张新的 user table

-- 面向对象
function user:new()
        u = {}
        setmetatable(u,{__index = self})
        return u
lisi = user:new()
lisi.name = '李四'
lisi.age = 25
print(lisi.name..lisi.age)
print(lisi.doSomething(lisi.name))
print(lisi.sleep(lisi.name))

运行结果:

-- import creates a base Error class and global funcs try(), catch(), finally() local Error = require ' lua _error ' -- do this anywhere in your code: try { function () -- make a call which could raise an error end , catch { function ( err ) -- handle the error finally { function ()
lua 本质上利用C函数来操作 LUA 虚拟机。 LUA 虚拟机对于C来说只是在堆上的内存对象。 lua 有自己的运行对象( 协程 ),每个 协程 有自己的调用栈。     比如下面的函数:     function add(x, y)         return x + y     如果x或y不能进行加法操作,在调用中就会产生异常。产生了异常,虚拟机需要对异常进行处理,最简单粗
一、显式抛错误或异常功能函数: 1、error (message [, level]) 功能:终止正在执行的函数,并返回message的内容作为错误信息(error函数永远都不会返回) 通常情况下,error会附加一些错误位置的信息到message头部. Level参数指示获得错误的位置, Level=