3 回答
TA贡献1796条经验 获得超4个赞
多次返回不是Go唯一的,并且不能替代异常。用C(或C ++)术语来说,它们是返回包含多个值的结构(对象)的简洁且用户友好的替代方法。
如果您仅此意思,它们确实提供了指示错误的便捷方法。
为什么将“资产”视为替代品?
断言最初用于调试。他们在程序处于“不可能”状态的情况下暂停了该程序,设计认为这种情况不应该发生,但是无论如何还是会发生。返回错误不太可能有太大帮助。代码库显然还无法正常工作,那么到底如何才能成功恢复呢?当有一个需要引起注意的错误时,您为什么还要这么做?
在生产代码中使用断言有些不同-显然存在性能和代码大小方面的顾虑,因此通常的方法是在代码分析和测试确信您“不可能”的情况确实不可能时,将它们删除。但是,如果您正在以这种偏执级别运行代码,它正在对自身进行审核,那么您还可能会偏执于:如果让代码继续在“不可能”状态下运行,那么它可能会做一些危险的事情:破坏有价值的数据,从而超出了堆栈分配的范围,并可能创建安全漏洞。同样,您只想尽快关闭。
您断言的内容确实与您使用异常的内容不同:当C ++和Java之类的编程语言为“不可能”的情况(logic_error
,ArrayOutOfBoundsException
)提供异常时,它们无意间鼓励一些程序员认为他们的程序应该尝试从真正无法控制的情况中恢复过来。有时这是适当的,但是出于充分的原因,这里有Java建议不要捕获RuntimeExceptions。偶尔捕获一个是一个好主意,这就是它们存在的原因。捕获它们几乎总是一个好主意,这意味着它们无论如何都等于暂停了程序(或至少是线程)。
TA贡献1854条经验 获得超8个赞
您应该阅读几篇有关异常的文章,以了解返回值不是异常。不能采用“带内” C方式或其他任何方式。
在不深入讨论的情况下,应该在发现错误条件的地方抛出异常,并在可以有意义地处理错误条件的地方捕获异常。返回值仅在层次结构堆栈中的第一个函数中处理,该函数可能会或不会如何处理问题。一个简单的示例是一个配置文件,该文件可以将值检索为字符串,并且还支持处理成类型的return语句:
class config {
// throws key_not_found
string get( string const & key );
template <typename T> T get_as( string const & key ) {
return boost::lexical_cast<T>( get(key) );
}
};
现在的问题是,如果找不到密钥,您将如何处理。如果您使用返回码(例如,在返回过程中),则问题在于get_as必须处理错误码get并采取相应措施。由于它并不真正知道该怎么办,因此唯一明智的做法是手动向上游传播错误:
class config2 {
pair<string,bool> get( string const & key );
template <typename T> pair<T,bool> get_as( string const & key ) {
pair<string,bool> res = get(key);
if ( !res.second ) {
try {
T tmp = boost::lexical_cast<T>(res.first);
} catch ( boost::bad_lexical_cast const & ) {
return make_pair( T(), false ); // not convertible
}
return make_pair( boost::lexical_cast<T>(res.first), true );
} else {
return make_pair( T(), false ); // error condition
}
}
}
该类的实现者必须添加额外的代码来转发错误,并且该代码与问题的实际逻辑混杂在一起。在C ++中,这可能比为多种赋值设计的语言(a,b=4,5)更为繁重,但是,如果逻辑取决于可能的错误(此处lexical_cast仅在有实际字符串的情况下执行调用),则必须缓存值变成变量。
TA贡献1871条经验 获得超13个赞
它不是Go语言,但在Lua中,多次返回是处理异常的极为常见的习惯用法。
如果您有类似的功能
function divide(top,bottom)
if bottom == 0 then
error("cannot divide by zero")
else
return top/bottom
end
end
然后,当bottom值为0时,将引发异常,并且程序的执行将停止,除非您将函数包装divide在pcall(或受保护的调用)中。
pcall 总是返回两个值:第一个是result是一个布尔值,指示该函数是否成功返回,第二个结果是返回值或错误消息。
以下(伪造的)Lua代码片段显示了此用法:
local top, bottom = get_numbers_from_user()
local status, retval = pcall(divide, top, bottom)
if not status then
show_message(retval)
else
show_message(top .. " divided by " .. bottom .. " is " .. retval)
end
当然pcall,如果您要调用的函数已经以的形式返回,则不必使用status, value_or_error。
多次回报对于Lua来说已经足够好了,所以虽然不能确保它对Go足够好,但是它支持了这个想法。
- 3 回答
- 0 关注
- 218 浏览
添加回答
举报