Go语言的创造者写道:

Go doesn't provide assertions. They are undeniably convenient, but our experience has been that programmers use them as a crutch to avoid thinking about proper error handling and reporting. Proper error handling means that servers continue operation after non-fatal errors instead of crashing. Proper error reporting means that errors are direct and to the point, saving the programmer from interpreting a large crash trace. Precise errors are particularly important when the programmer seeing the errors is not familiar with the code.

你对此有什么看法?


当前回答

不,只要您按照预期使用assert,它就没有错。

也就是说,它应该用于在调试期间捕捉“不可能发生”的情况,而不是正常的错误处理。

断言:程序逻辑本身的失败。 错误处理:错误的输入或系统状态,不是由于程序中的错误造成的。

其他回答

我对这些捍卫assert的答案的问题是,没有人清楚地说明它与常规致命错误的不同之处,以及为什么断言不能成为异常的子集。现在,如果异常从未被捕获,该怎么办?从命名法上看,这是一种断言吗?而且,为什么要在语言中强加一个可以引发/nothing/可以处理的异常的限制呢?

我从不使用assert(),示例通常是这样的:

int* ptr = new int[10];
assert(ptr);

这很糟糕,我从来没有这样做过,如果我的游戏分配了一堆怪物怎么办?为什么我要让游戏崩溃,相反,你应该优雅地处理错误,所以可以这样做:

CMonster* ptrMonsters = new CMonster[10];
if(ptrMonsters == NULL) // or u could just write if(!ptrMonsters)
{
    // we failed allocating monsters. log the error e.g. "Failed spawning 10 monsters".
}
else
{
    // initialize monsters.
}

断言并不邪恶,但很容易被滥用。我非常同意“断言经常被用作一种拐杖,以避免考虑正确的错误处理和报告”的说法。我经常看到这种情况。

就我个人而言,我确实喜欢使用断言,因为它们记录了我在编写代码时可能做出的假设。如果在维护代码时这些假设被打破了,那么可以在测试期间检测到问题。但是,在进行产品构建时(即使用#ifdefs),我确实强调要从代码中剥离出每个断言。通过剥离产品构建中的断言,我消除了任何人将其误用为拐杖的风险。

断言还有另一个问题。断言只在运行时进行检查。但是通常情况下,您想要执行的检查可以在编译时执行。最好在编译时检测问题。对于c++程序员,boost提供了BOOST_STATIC_ASSERT,它允许您执行此操作。对于C程序员,本文(链接文本)描述了一种可用于在编译时执行断言的技术。

总之,我遵循的经验法则是:不要在生产构建中使用断言,如果可能的话,只对在编译时无法验证的东西使用断言(即,必须在运行时检查)。

作为附加信息,go提供了一个内置函数panic。这可以用来代替assert。如。

if x < 0 {
    panic("x is less than 0");
}

Panic将打印堆栈跟踪,因此在某种程度上它具有assert的目的。

我非常不喜欢断言。但我不会说他们是邪恶的。

基本上,assert将做与未检查异常相同的事情,唯一的例外是assert(通常)不应该为最终产品保留。

If you build a safety net for yourself while debugging and building the system why would you deny this safety net for your customer, or your support help desk, or anyone that will get to use the software that you are currently building. Use exceptions exclusively for both asserts and exceptional situations. By creating an appropriate exception hierarchy you will be able to discern very quickly one from the other. Except this time the assert remains in place and can provide valuable information in case of failure that would otherwise be lost.

因此,我完全理解Go的创建者完全删除断言并强迫程序员使用异常来处理这种情况。对此有一个简单的解释,异常只是一种更好的工作机制为什么要坚持使用古老的断言?