将错误变量用作包级别变量与全局变量的区别

huangapple go评论84阅读模式
英文:

Using an error variable as package-level vs global variable

问题

使用Go语言编写一个函数,该函数使用自定义错误变量,例如:

func readEnv() (map[string]string, error) {
	var ErrConfig = errors.New("Configuration Error: Variables starting with the right prefix are not even")

if this {
  return nil, ErrConfig
}

我将其声明为局部变量,以避免将其声明为包级变量,这是不推荐的(如果我没有记错的话,这也是linter标记的问题)。

问题出现在当我想对这个函数进行单元测试并测试错误路径时(在这种情况下,函数应该返回上述错误,但是却无法访问)。现在,我能想到的唯一解决方法是在我的表格测试中重新声明这个变量。

哪种方式是正确的?将ErrConfig声明为包级变量还是只在单元测试函数中重新声明它?

英文:

Using the Go language I am writing a function that uses a custom error variable, e.g.

func readEnv() (map[string]string, error) {
	var ErrConfig = errors.New("Configuration Error: Variables starting with the right prefix are not even")

if this {
  return nil, ErrConfig
}

I declare this as a local var to avoid declaring it as a package-level var which is not recommended (and marked as issue from the linter if I am not mistaken)

The problem arises when I want to unit test this fxn and want to also test the error path (in which case the fxn should return the above error which however has not access to.). Now, the only way I can think of to address this is to re-declare this variable in my table test.

Which is the right way? Declaring ErrConfig as a package-level variable or just re-declaring it in the unit test fxn?

答案1

得分: 3

对于readEnv()的调用者来说,返回的错误是否重要呢?

如果不重要,你的测试也不需要关心,只需检查返回的错误是否为nil

如果重要,那么在你目前的解决方案中,调用者在测试中无法做得比你更好。如果重要且客户端应该能够知道,你必须导出某种机制来测试/检查返回的错误。

一种解决方案是将ErrConfig移动到包级别的变量。这是被接受的,在标准库中也被多处使用,例如io.EOFio.ErrClosedPipe

然而,这并不是唯一的解决方案。你可以将ErrConfig设置为未导出的变量(例如errConfig),并提供一个导出的函数来测试错误,例如:

var errConfig = errors.New("Configuration Error: Variables starting...")

func IsErrConfig(err error) bool {
    return err == errConfig
}

这也在标准库的许多地方使用,例如os.IsExist()os.IsNotExist()

你还可以使返回的错误实现一个导出的接口,调用者可以使用类型断言来检查返回的错误是否实现了该接口,从而为返回的错误提供额外的功能。

英文:

Does it matter to the caller of readEnv() what error you return?

If it doesn't matter, your test shouldn't care either, just check if the returned error is nil or not.

If it matters, in your current solution callers can't do any better than you in your tests. If it matters and clients should be able to tell, you have to export some kind of mechanism to test / examine the returned error.

One solution is to move ErrConfig to a package level variable. This is accepted, used numerous places in the standard lib too, e.g. io.EOF, io.ErrClosedPipe.

This is not the only solution though. You could make Errconfig unexported (e.g. errConfig), and provide an exported function to test an error, e.g.:

var errConfig = errors.New("Configuration Error: Variables starting...")

func IsErrConfig(err error ) bool {
    return err == errConfig
}

This is also used in many places in the standard lib, e.g. os.IsExist(), os.IsNotExist()

You could also make the returned error implement an exported interface, and callers can check using a type assertion if the returned error implements that, providing extra functionality for the returned error.

huangapple
  • 本文由 发表于 2021年8月10日 15:19:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/68722501.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定