A use case for importing with blank identifier in golang

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

A use case for importing with blank identifier in golang

问题

Go编程语言规范中指出:“为了仅仅导入一个包以便进行副作用(初始化),可以使用空白标识符作为显式的包名。”

例如:

import _ "foo/bar"

我很难想象这种结构的用例。在https://stackoverflow.com/questions/24425002/usage-of-the-import-statement/24425363#24425363的接受答案中提到了一个用例,其中数据库驱动程序可以被加载,而不需要导入程序使用该包的任何导出函数,但它没有提供详细的细节给读者想象。

是否有现实生活中的例子(包括代码片段和解释)来说明这个用例?

英文:

The Go programming language specification states: "To import a package solely for its side-effects (initialization), use the blank identifier as explicit package name."

For example:

import _ "foo/bar"

I am having difficulty imagining a use case for this construct. The accepted answer for https://stackoverflow.com/questions/24425002/usage-of-the-import-statement/24425363#24425363 mentions a use case where a database driver may be loaded without the need for the importing program to use any of the exported functions of that package, but it leaves out the details to reader's imagination.

Are there real life examples (with code snippets and explanation) that illustrate this use case?

答案1

得分: 27

我正在编写一个调整图像大小的程序。我希望它能够识别不同格式的图像,如JPEGPNGGIF,并将它们转换为JPEG格式。

所以除了imageimage/jpeg包之外,我还需要导入image/pngimage/gif包,只是为了注册它们各自的解码器。

如果我没有导入它们,这个程序将只能读取JPEG格式的图像。

package main

import (
  "image"
  "image/jpeg" // 我希望将图像导出为JPEG格式
  _ "image/png"
  _ "image/gif"
)

// ...

来自image包的相关文档:

解码任何特定的图像格式需要先注册一个解码器函数。注册通常是作为初始化该格式包的副作用自动完成的,因此,要解码PNG图像,只需要导入:

import _ "image/png"
英文:

I was writing a program that resizes images. I wanted it to be able to recognize images in different formats like JPEG, PNG, GIF and convert them to JPEG.

So in addition to the image and image/jpeg packages, I also had to import image/png and image/gif only to register their respective decoders.

Had I not imported those, the scaler would only be able to read JPEG images.

package main

import(
  "image"
  "image/jpeg" // I wanted to export the images as JPEG
  _ "image/png"
  _ "image/gif"
)

// ...

The relevant documentation from the image package:

>Decoding any particular image format requires the prior registration of a decoder function. Registration is typically automatic as a side effect of initializing that format's package so that, to decode a PNG image, it suffices to have:
>
> import _ "image/png"

答案2

得分: 24

这是因为**init函数**的存在。

每个源文件都可以定义自己的无参数init函数来设置所需的状态。(实际上,每个文件可以有多个init函数。)

最后的最后,init的调用是真正的最后:在包中的所有变量声明都评估完其初始化器之后才调用init函数,而这些初始化器只有在所有导入的包都初始化完之后才会被评估。

这就是在“What does an underscore in front of an import statement mean in Go”中提到的go-sqlite3的工作原理。

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

在“Understanding Golang Packagese”中还有另一个例子:

在某些情况下,我们可能只需要导入一个包来调用其init方法,而不需要调用包的其他方法。
如果我们导入了一个包但在程序中没有使用该包的标识符,Go编译器会显示错误
在这种情况下,我们可以使用一个空白标识符(_)作为包的别名,这样编译器就会忽略未使用包标识符的错误,但仍然会调用init函数。

英文:

This is because of the init function

> each source file can define its own niladic init function to set up whatever state is required. (Actually each file can have multiple init functions.)
>
> And finally means finally: init is called after all the variable declarations in the package have evaluated their initializers, and those are evaluated only after all the imported packages have been initialized.

That is how the go-sqlite3 mentioned in "What does an underscore in front of an import statement mean in Go" works.

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

You have another example in "Understanding Golang Packagese":

> In some contexts, we may need to import a package only for invoking it’s init method, where we don’t need to call forth other methods of the package.
If we imported a package and are not using the package identifier in the program, Go compiler will show an error.
In such a situation, we can use a blank identifier ( _ ) as the package alias name, so the compiler ignores the error of not using the package identifier, but will still invoke the init function.

答案3

得分: 4

一个使用案例是当你只需要init函数执行一些初始化操作(例如注册自己,这样你就不需要显式调用它们)。

一个例子是注册一些数据库驱动程序

import (
    "database/sql"
    _ "github.com/ziutek/mymysql/godrv"
)
英文:

A use case is when what you want is only the init function doing some initialization (for example registering themselves so that you don't have to explictely call them).

An exemple is the registring of some database drivers :

import (
    "database/sql"
    _ "github.com/ziutek/mymysql/godrv"
)

huangapple
  • 本文由 发表于 2014年11月17日 20:20:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/26972615.html
匿名

发表评论

匿名网友

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

确定