在导入语句前面加下划线的含义是什么?

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

What does an underscore in front of an import statement mean?

问题

在这段来自go-sqlite3的代码中:

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

import语句中的下划线(underscore)代表匿名导入。匿名导入意味着导入的包将被编译器加载,但在代码中无法直接使用该包的标识符。在这种情况下,_ "github.com/mattn/go-sqlite3"表示导入了github.com/mattn/go-sqlite3包,但在代码中没有直接使用该包的标识符。通常情况下,这样的导入用于执行包的初始化操作,而不需要在代码中直接使用该包。

英文:

In this code from go-sqlite3:

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

what does the underscore in the import statement mean?

答案1

得分: 324

这是用于仅导入一个包以获取其副作用的情况。

根据Go规范

要仅为了其副作用(初始化)而导入一个包,请使用下划线作为显式包名:

import _ "lib/math"

在sqlite3中

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

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

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

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

It's for importing a package solely for its side-effects.

From the Go Specification:

> To import a package solely for its side-effects (initialization), use the blank identifier as explicit package name:
>
> go
> import _ "lib/math"
>

In sqlite3

In the case of go-sqlite3, the underscore import is used for the side-effect of registering the sqlite3 driver as a database driver in the init() function, without importing any other functions:

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

Once it's registered in this way, sqlite3 can be used with the standard library's sql interface in your code like in the example:

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

答案2

得分: 63

虽然其他答案已经完全描述了这个问题,但对于“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) }
英文:

While other answers described it completely, for "Show me The Code" people, this basically means: create package-level variables and execute the init function of that package.

And (if any) the hierarchy of package-level variables & init functions of packages that, this package has imported.

The only side effect that a package can make, without being actually called, is by creating package-level variables (public or private) and inside it's init function.

Note: There is a trick to run a function before even init function. We can use package-level variables for this by initializing them using that function.

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

var (
	Num = theVeryFirstFunction()
)

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

答案3

得分: 23

以下是要翻译的内容:

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

这要么是一个正在进行的工作,要么是为了副作用而导入的。在这种情况下,我认为它是为了副作用而导入的,正如文档中所描述的。

英文:

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

It's either a work in progress, or imported for side effects. In this case, I believe it's for the side effects, as described in the doc.

答案4

得分: 6

假设你有一个Animal包。你的主文件想要使用这个Animal包来调用一个名为Speak的方法,但是有许多不同类型的动物,每个动物都实现了自己的通用Talk方法。所以假设你想要调用Animal包中实现的Speak方法,该方法在内部调用了每个动物包中实现的Talk方法。在这种情况下,你只需要做一个import _ "dog",这实际上会调用dog包中定义的init方法,该方法实际上会向Animal包注册一个Talk方法,而Animal包也会导入它。

英文:

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.

答案5

得分: 1

作为我在Go语言中的新手,这个定义使它更清晰:

下划线是Go语言中的一个特殊字符,它充当空容器的角色。由于我们导入了一个包但没有使用它,Go编译器会对此发出警告。为了避免这种情况,我们将该包的引用存储在_中,Go编译器将简单地忽略它。
有时,使用下划线对包进行别名处理,虽然看起来没有任何作用,但却非常有用,特别是当你想要初始化一个包但不使用它时。

链接

英文:

As I'm new in Go, this definition made it more clear:

> Underscore is a special character in Go which acts as null container. Since we are importing a package but not using it, Go compiler will complain about it. To avoid that, we are storing reference of that package into _ and Go compiler will simply ignore it.
Aliasing a package with an underscore which seems to do nothing is quite useful sometimes when you want to initialize a package but not use it.

Link

huangapple
  • 本文由 发表于 2014年1月20日 01:25:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/21220077.html
匿名

发表评论

匿名网友

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

确定