import _ "hogehoge"
の _
は、どういう意味があるんだろうと気になったので調べました。
init()の実行が理由
packageの中身を利用せずに、init()関数が必要な場合に利用するようです。 なので次のように動作を試してみました。
main.go
package main
import (
"fmt"
_ "github.com/sourjp/practice/hello"
)
func main() {
fmt.Println("Hi")
}
hello/hello.go
package hello
import "fmt"
func init() {
fmt.Println("hello")
}
実行してみるとpackage helloを使いませんが、中に定義されているinit()が実行されていることがわかります。
$ go run main.go
hello
Hi
次に実際のpackageでの使われ方をみていきます。
package imageの場合
package imageでは、Decode()を行うのにRegistration()で拡張子を登録する必要があります。
Values of the Image interface are created either by calling functions such as NewRGBA and NewPaletted, or by calling Decode on an io.Reader containing image data in a format such as GIF, JPEG or PNG. 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"
package image/pngを覗いてみるとまさにこれですね。
func init() {
image.RegisterFormat("png", pngHeader, Decode, DecodeConfig)
}
つまり import _ "image/png"
を実行すると、init()
の image.RegisterFormat()
が実行されるので image.Decode()
で変換できるということです。
package pgの場合
DB driverを利用する時にも、import _ "github.com/lib/pq"
と書きます。この時は何しているんでしょう?
init()
を見つけました。これも、sqlのdriverとして登録してくれています。これによって、sql.Open("postgres", ...)
が利用できるようなるということですね。
func init() {
sql.Register("postgres", &Driver{})
}
まとめ
学んだことを整理します。
import _ "hoge"
はhoge packageのinit()を実行する- 利用するケースは、それをwrapしたpackageがある時(package image, package sqlなど)