从 Lua 函数返回多个值时,如何最佳地返回错误。

我有一个 Lua 函数,需要多个参数,并且返回与参数数量相同的值。每个返回值对应一个参数。为了说明,考虑一个从数据库读取键值对的值的函数:

val1, val2, val3 = my_function("key1", "key2", "key3");
val1 = my_function("key1");

如何从 my_function 返回错误?(例如,如果提供的“键”无效)

我了解一种方法是在错误时返回两个值,nil 和错误字符串。例如:

val1, val2, val3 = my_function("key1", "key2", "key3");
if val1 then
    -- 使用 val1,val2 和 val3。
else
    print("ERROR: " .. val2);
end

编辑

一些附加要点:

  1. 这个 Lua 脚本是使用 lua_pcall() 从 C 程序中执行的。
  2. 如果脚本失败,则 C 程序不能中止。
  3. my_function() 是在 C 中实现的。
  4. my_function() 失败时,它也应该返回错误代码(或消息)表明失败的原因。

原文链接 https://stackoverflow.com/questions/8752855

点赞
stackoverflow用户312586
stackoverflow用户312586

Lua中抛出错误的标准方式是通过 error 函数(manual, api) 或者通过 assert (其内部也是使用 error)。

因为你的函数是C函数,所以你应该在函数内部调用 lua_error, 以获得相同的效果。

但要记住,你的函数现在是 "不安全的"。如果不进行修改,下面的代码将会执行类似 "抛出异常" 的操作,从而停止程序,如果 key1、key2 或 key3 是 "不正确的":

val1, val2, val3 = my_function("key1", "key2", "key3")

有时,如果输入错误,让程序 "崩溃" 也是可以接受的。根据你的设置,用户将会得到最后一个错误消息和堆栈跟踪,或类似的东西。

如果 "让程序崩溃" 不是一个选项,你可以使用 pcall 函数来做类似 "try-catch" 的操作,并添加一个名为 ok 的新变量:

ok, val1, val2, val3 = pcall(my_function, "key1", "key2", "key3")
if ok then
  -- 使用val1、val2和val3。
else
  print("ERROR: " .. val1) -- 注意,这里使用的是val1,而不是val2。
end

请注意,你不必将 pcall 放在 my_function 正上方。就像异常一样,错误恢复可以发生在更高的调用链中:在调用 my_function 的函数中、调用那个函数的函数中等等。例如,如果你从一个名为 parent 的函数中调用 my_function,而 parent 又被一个名为 grandParent 的函数调用,你可以这样做:

-- parent 是 "不安全的",因为 my_function 是 "不受保护的"
function parent(key1, key2)
  local val1, val2, val3 = my_function(key1, key2, "key3")
  return val1, val2, val3
end

-- grandParent 在 "安全" 的方式下调用 parent
function grandParent()
  local ok, val1, val2, val3 = pcall(parent, "key1", "key2")
  if ok then
    -- 使用val1、val2和val3。
  else
    print("ERROR: " .. val1)
  end
end
2012-01-06 10:24:12
stackoverflow用户107090
stackoverflow用户107090

通常的做法是当程序无法恢复(例如,错误的文件句柄)时抛出错误,当它可以恢复(例如,找不到文件)时发出信号。在你的情况下,我认为对于无效的键,简单地返回 nil 是最好的方法。

The usual practice is to throw errors when the program cannot recover (bad file handle for instance) and signal errors when it can recover (file not found for instance). In your case, I think that simply returning `nil` for invalid keys is the best way.
2012-01-06 10:59:33