Tip #15 什么时候使用空白导入和点导入?

原始链接:Golang Tip #15: When to use Dot (.) Import and Blank (_) Import?

空白导入(import _ "package")

当你使用“空白导入”时,你引入了一个包,但并不是为了直接访问它的内容(如函数或变量),而是为了它的副作用。

那么,什么是副作用呢?

副作用是指一个包在被导入时可能执行的任何操作,如初始化、注册、设置环境等。

这通常发生在包的 init() 函数中,该函数在包被导入时自动运行。

即使 main 函数是空的,当你运行上面的代码时,logger 包的 init() 函数会在导入时运行,向控制台打印 “Logger package initialized”。

使用时机是什么?

主要规则是:

  • 通常在 main 包中使用。
  • 在那些需要引入副作用才能正确运行的测试中使用。

一个常见的例子是在使用 database/sql 包的程序中导入数据库驱动包。

数据库驱动包被导入是因为其副作用(例如,将自己注册为 database/sql 的驱动)。

点导入(import . "package")

使用“点导入”有点特别。

这意味着你可以直接使用那些导出的项,就像它们是在当前包中定义的一样。

看,我们不需要指定 math.Abs 或 math.Pi。

那么,何时使用它?

这种形式在测试中特别有用。

尤其是在处理难以轻易解决的循环依赖时。

给你举个例子。

想象你有两个包:

  • mypackage:这是你的 main 包,包含你正在测试的功能。
  • testhelpers:一个提供测试辅助函数的独立包。

其中一个辅助函数需要使用 mypackage,从而创建了从 testhelpers 到 mypackage 的依赖。

现在,你正在为 mypackage 编写测试,并希望使用 testhelpers 中的辅助函数。

但由于 testhelpers 已经导入了 mypackage,你不能简单地将 testhelpers 导入到你的 mypackage_test.go 中,否则会创建循环依赖。

译者注:上面隐含了 mypackage_test.go 所在的包是 main 包。

为了解决这个问题,测试文件声明自己为 mypackagetest 包,并使用点导入直接访问 mypackage 的标识符,就像它在 mypackage 内部定义的一样。

建议谨慎使用这两种包导入方式,因为它们可能会使代码更难阅读。