在go-sqlite3的代码中:

import (
        "database/sql"
        "fmt"
        _ "github.com/mattn/go-sqlite3"
        "log"
        "os"
)

import语句中的下划线是什么意思?


当前回答

这是为了只因为副作用而导入一个包。

Go规范:

如果只导入一个包的副作用(初始化),使用空白标识符作为显式的包名: 导入_ "lib/math"

在sqlite3

在go-sqlite3的情况下,下划线导入用于在init()函数中将sqlite3驱动程序注册为数据库驱动程序的副作用,而不导入任何其他函数:

sql.Register("sqlite3", &SQLiteDriver{})

一旦以这种方式注册,sqlite3就可以在你的代码中与标准库的sql接口一起使用,如示例所示:

db, err := sql.Open("sqlite3", "./foo.db")

其他回答

因为我是围棋新手,这个定义让我更清楚:

下划线是Go中的一个特殊字符,充当空容器。因为我们导入了一个包,但没有使用它,Go编译器会报错。为了避免这种情况,我们将该包的引用存储到_中,Go编译器将简单地忽略它。 当你想初始化一个包但又不使用它时,用下划线对一个包进行别名(它似乎什么都不做)是非常有用的。

Link

https://golang.org/doc/effective_go.html#blank

要么还在研究中,要么就是因为副作用而引进的。在这种情况下,我认为这是为了治疗副作用,正如医生所说。

这是为了只因为副作用而导入一个包。

Go规范:

如果只导入一个包的副作用(初始化),使用空白标识符作为显式的包名: 导入_ "lib/math"

在sqlite3

在go-sqlite3的情况下,下划线导入用于在init()函数中将sqlite3驱动程序注册为数据库驱动程序的副作用,而不导入任何其他函数:

sql.Register("sqlite3", &SQLiteDriver{})

一旦以这种方式注册,sqlite3就可以在你的代码中与标准库的sql接口一起使用,如示例所示:

db, err := sql.Open("sqlite3", "./foo.db")

虽然其他答案完全描述了它,但对于“Show me The Code”的人来说,这基本上意味着:创建包级别的变量并执行包的init函数。

以及(如果有的话)包级别变量的层次结构和包的init函数,该包已导入。

一个包在不被实际调用的情况下所能产生的唯一副作用是在它的init函数中创建包级变量(公共或私有)。

注意:在init函数之前运行一个函数是有技巧的。通过使用该函数初始化包级变量,我们可以为此使用包级变量。

func theVeryFirstFunction() int {
    log.Println("theVeryFirstFunction")
    return 6
}

var (
    Num = theVeryFirstFunction()
)

func init() { log.Println("init", Num) }

Let's say you have an Animal package. And your main file wants to use that Animal package to call a method called Speak but there are many different types of animals and each animal implemented their own common Talk method. So let's say you want to call a method Speak implemented in the Animal's package which internally calls Talk method implemented in each of the animal's package. So in this case you just want to do an import _ "dog" which will actually call the init method defined inside the dog package which actually registers a Talk method with the Animal package which it too imports.