【问题标题】:Best practice for returning an error from a lua function returning multiple values从返回多个值的 lua 函数返回错误的最佳实践
【发布时间】:2012-02-03 21:19:28
【问题描述】:

我有一个 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
    -- Use val1, val2, and val3.
else
    print("ERROR: " .. val2);
end

编辑

补充几点:

  1. 正在使用 lua_pcall() 从 C 程序中执行 lua 脚本。
  2. 如果脚本失败,C 程序不得中止。
  3. my_function() 用 C 实现。
  4. my_function() 失败时,它还应该返回一个错误代码(或消息),指出失败的原因。

【问题讨论】:

    标签: lua


    【解决方案1】:

    在 Lua 中抛出错误的标准方法是通过错误函数(manualapi)或通过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
      -- Use val1, val2, and val3.
    else
      print("ERROR: " .. val1) -- notice that we use val1 here, not val2
    end
    

    请注意,您不必将pcall 完全放在my_function 之上。与异常一样,错误恢复可能发生在调用链的更高位置:在调用 my_function 的函数中,或在调用该函数的函数中,等等。例如,如果您从名为 parent 的函数中调用 my_function,并且来自grandParent 的父母,您可以这样做:

    -- parent is "insecure" since my_function is "unprotected"
    function parent(key1, key2)
      local val1, val2, val3 = my_function(key1, key2, "key3")
      return val1, val2, val3
    end
    
    -- grandParent calls parent in a "safe" way
    function grandParent()
      local ok, val1, val2, val3 = pcall(parent, "key1", "key2")
      if ok then
        -- Use val1, val2, and val3.
      else
        print("ERROR: " .. val1)
      end
    end
    

    【讨论】:

    • 我已编辑问题以澄清几点。由于 lua 脚本(最终调用 my_function())是从 C 中使用 lua_pcall() 运行的,所以 my_function() 是否应该像上面描述的那样返回一个“ok”变量? (例如ok, val1, val2, val3 = my_function())。
    • @Ben,是的,我会包含一个额外的ok 值——这似乎是最干净的方式。我还建议对设计进行修改;由于这两个函数都在 C 中,因此忘记 Lua 并在 C 中做所有事情可能会更简单(更快)。
    • @kikto,感谢您的澄清。在这种情况下,使用 lua(或等效的)来扩展产品对我来说绝对是有意义的。
    • @Ben 这种方法有一个缺点:没有明确的方法来区分单个参数和多个参数中的错误(例如,key1 确实存在,但 key2 或 key3 都存在)。你可以不打扰;提供不同的错误信息;或者不是每个参数返回一个值,而是总是返回 2(ok1, val1, ok2, val2 等);或者在错误的情况下返回一个带有错误信息的表(只有在通常返回值不是表时才有效)。
    【解决方案2】:

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

    【讨论】:

    • 如果我希望 my_function() 也返回失败的原因,您是否主张如果 val1, val2, val3 = my_function() 失败,val1 应该是 nilval2 应该是错误代码/留言?
    • @Ben,不,我认为唯一的原因是“无效密钥”。
    猜你喜欢
    • 2018-11-01
    • 2015-09-01
    • 2017-07-23
    • 2013-08-12
    • 2021-11-14
    • 1970-01-01
    • 2013-05-12
    • 2018-12-22
    • 1970-01-01
    相关资源
    最近更新 更多