Go语言 是否可以假定strconv.Parse * 函数返回的任何错误都是由于错误的输入数据造成的?

jecbmhm3  于 2023-09-28  发布在  Go
关注(0)|答案(2)|浏览(102)

在最近的一次代码评审中,一位评审员对我如何处理从strconv.ParseUint()返回的错误提出了异议。这个函数返回转换后的uint值和一个*strconv.NumError具体类型的错误。文档中提到了两个可能返回的这种类型的sentinel错误(ErrSyntaxErrRange),这两个错误都意味着向它提供了错误的数据。根据函数的界面,任何其他错误也可能出现。
对于我的用例,我需要知道我拥有的字符串值是否值得转换为uint。如果ParseUint返回一个错误,并且是一个哨兵错误,那么我得到了我的答案。但是如果返回的错误不是这两个,那么我就返回它并停止执行。我的审稿人Assert,我应该假设从ParseUint返回的 any 错误意味着我给了它错误的数据,没有必要检查sentinel错误,没有理由检查sentinel错误,也没有返回错误(在我的用例中)。他们链接到go标准库中的一个例子,其中来自ParseUint的错误被视为对错误输入数据的检查,并且永远不会返回,并表示有很多这样的例子。
虽然我当然可以理解,一定存在一种算法,在给定良好数据和足够资源的情况下,总是能够计算出所需的结果,但真实的世界并不总是与理论理想相匹配。我在库的文档中找不到任何东西说它不会,也永远不会,因为除了坏数据之外的任何其他原因返回错误。标准库有一个,也许还有很多这样的例子,这一方面让人放心,另一方面又让人害怕,介于“两个错误并不意味着一个正确”和“他们正在做,所以我们也必须安全地做”之间。
这只是图书馆的文档少了一句话的情况吗?或者,当两个sentinel错误都不是的时候,返回错误是好的吗?我该怎么推理呢?

ig9co6j1

ig9co6j11#

是的,可以假定strconv.ParseXXX函数的错误是由于错误的输入数据造成的。
从您提到的文档页面:
ParseInt返回的错误具有具体类型 *NumError,并包含err. error = s。如果s为空或包含无效数字,则err.Err = ErrSyntax,返回值为0;如果对应于s的值不能由给定大小的有符号整数表示,则err.Err = ErrRange,并且返回的值是适当的bitSize和sign的最大幅度整数。
我读这段话的方式是“任何来自strconv.ParseXXX的错误都是NumError,它要么是由于无效的数字,要么是由于位大小范围错误”。我的理解是,godoc试图尽可能完整地概述函数调用的期望范围。
因此,我认为可以安全地假设这些是您可能从strconv.ParseXXX函数返回的 * 唯一 * 错误。如果有其他的东西回来,我会认为这是一个文档错误。
回答你最后一个问题:您在标准库调用此函数时观察到的模式是正确的。将错误作为一个整体返回,让调用者决定如何处理它。哨兵错误是为了帮助您知道哪里出错了,并表示这些函数可能出现的错误的全部范围。

igetnqfo

igetnqfo2#

我不认为有一个正确的答案。
在大多数情况下,如果ParseUint返回一个错误,则假定它是一个错误的输入并返回该错误。您甚至不检查它是否是两种具体错误类型之一。ParseUint在逻辑上确实没有其他错误可以返回。对于大多数自包含的解析/解码/解组函数,所有错误都是输入错误的不同变体。
在某些情况下,您可能需要检查确切的错误类型。例如,如果ParseUint返回ErrRange,您可能希望尝试将其解析为big.Int。然后检查错误类型是有意义的。
Go语言的接口实现可能会让一些人感到困惑,尤其是那些习惯于用不同语言处理错误/异常的人。Go函数返回接口error类型来表示错误,而不是具体的错误。从函数返回一个具体类型的错误只会带来麻烦。因此,即使一个函数可以返回一个具体类型的错误,它也被声明为返回error

相关问题