协程执行也有返回值,并且每次执行结束或暂停都有返回值,每次继续都有不同的入参
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=