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(通常)不应该为最终产品保留。

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

其他回答

Assert非常有用,可以在出现意外错误时通过在出现问题的第一个迹象时停止程序来节省大量回溯时间。

另一方面,断言很容易被滥用。

int quotient(int a, int b){
    assert(b != 0);
    return a / b;
}

正确的说法应该是:

bool quotient(int a, int b, int &result){
    if(b == 0)
        return false;

    result = a / b;
    return true;
}

所以…从长远来看……从大局来看……我必须同意断言可能会被滥用。我一直都这么做。

当我看到这个的时候,我真想踢作者的头。

我在代码中一直使用断言,并最终在编写更多代码时将它们全部替换掉。当我还没有编写所需的逻辑时,我就会使用它们,当我运行到代码时,我想要得到警告,而不是编写一个将在项目接近完成时删除的异常。

异常也更容易融入到产品代码中,这是我不喜欢的。断言比抛出新异常("一些通用的msg或'pretend i am An assert'")更容易注意到;

这种情况经常出现,我认为让断言辩护令人困惑的一个问题是,它们通常基于参数检查。所以考虑一下这个不同的例子,当你使用断言时:

build-sorted-list-from-user-input(input)

    throw-exception-if-bad-input(input)

    ...

    //build list using algorithm that you expect to give a sorted list

    ...

    assert(is-sorted(list))

end

您对输入使用异常是因为您预计有时会得到错误的输入。您断言对列表进行排序是为了帮助您找到算法中的bug,根据定义,这是您所不期望的。断言只存在于调试版本中,因此即使检查的开销很大,您也不介意对例程的每次调用都进行检查。

您仍然需要对产品代码进行单元测试,但这是确保代码正确的一种不同的补充方式。单元测试确保您的例程符合其接口,而断言是一种更细粒度的方法,以确保您的实现完全按照您的期望进行。

与其说是坏事,不如说是适得其反。永久性错误检查和调试是分开的。Assert让人们认为所有的调试都应该是永久性的,使用过多会导致大量的可读性问题。在需要时,永久错误处理应该比这种方法更好,由于assert会导致自己的错误,因此这是一种非常值得怀疑的实践。

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

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

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