go学习: 副作用导入

2024 / 10 / 17

在 Go 语言的 import 语句中,前面加上 _(空白标识符)意味着你导入了这个包,但并不会直接使用包中的任何标识符(如函数、类型等)。这种导入方式叫做 匿名导入 副作用导入它的作用是执行包的初始化函数,而不需要直接使用包中的任何内容。

为什么会有 _ ?

import ( "fmt" _ "github.com/go-sql-driver/mysql" // 导入 MySQL 驱动 )

这里导入 github.com/go-sql-driver/mysql 时使用了 _,原因是你只需要 初始化 这个包,但不会显式地在代码中调用它的任何函数或类型。Go 语言会在程序启动时自动执行该包的初始化逻辑。

在 go-sql-driver/mysql 中,这个初始化逻辑主要是 注册 MySQL 驱动 到 Go 的标准库 database/sql 包中。虽然你没有在代码中直接使用 mysql 包中的任何内容,但通过 database/sql 来连接 MySQL 数据库时,实际上已经间接使用了这个包的功能。

副作用导入的典型用例

  1. 注册驱动:像 MySQL 这样的数据库驱动,需要注册到 database/sql 包中。这种情况下,我们只需要导入驱动包的副作用(初始化过程),而不需要直接调用该包的内容。

  2. 在 go-sql-driver/mysql 包中,init() 函数会被自动调用,负责将 MySQL 驱动注册到 database/sql 包中。

func init() { sql.Register("mysql", &MySQLDriver{}) }

因此,虽然你没有显式使用 mysql 包的任何函数或类型,但 MySQL 驱动已经注册到 database/sql,你可以使用它来创建 MySQL 连接。

  1. 执行初始化逻辑:某些包可能会在初始化时执行某些副作用,比如环境设置、变量初始化等。即便你没有使用包内的具体内容,初始化时就会执行这些逻辑。

_ 的作用

  • 避免未使用包的编译错误:Go 语言对未使用的导入包会报错。加上 _ 告诉编译器你确实需要这个包的副作用(初始化),即使不直接使用包中的标识符。

  • 触发包的 init() 函数:在 Go 中,每个包都可以定义一个 init() 函数,它会在包被导入时自动运行,_ 确保了 init() 函数会被调用。

总结

  • 在 Go 代码中,_ "github.com/go-sql-driver/mysql" 表示导入了 MySQL 驱动,但不会直接在代码中引用它。

  • 它的作用是让包的 init() 函数执行,从而注册 MySQL 驱动到 Go 的 database/sql 包中,使你可以通过 database/sql 来使用 MySQL。

  • 这种导入方式广泛用于驱动、插件或有副作用的初始化代码场景。