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


Written By - Tuan Nguyen
Advertisement

The underscore in front of an import statement is solely for its side-effects.

An import declaration declares a dependency relation between the importing and imported package. It is illegal for a package to import itself, directly or indirectly, or to directly import a package without referring to any of its exported identifiers. To import a package solely for its side-effects (initialization), use the blank identifier as explicit package name:

import _ "lib/math"

 

When should we use underscore for import in Golang

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.

Fixing imported but not used

We can use a blank identifier (_) before the package name that will not be used as following code:

package main

import (
	"fmt"
	_ "math"
)

func main() {
	name := "GoLinuxCloud"
	age := 1
	fmt.Println("My name is:", name, "and my age is:", age)
}

 

Fixing declared but not used

In the below code, two variables page and author are declared but author was not used. To avoid compile error, you have to assign the variable to a blank identifier (_) as the code shown below:

package main

import (
	"fmt"
)

func main() {
	page := "GolinuCloud"
	author := "Anonymous Author"

	fmt.Println("Name is:", page)
        _ = author
}

Output:

Page is: GolinuCloud

 

Fixing imported but not used

In the example below, we will import the math package but not use it at all.

Advertisement
package main

import (
	"fmt"
	"math"
)

func main() {
	fmt.Println("This is an example of importing packages in Golang!")
}

Output:

$ go run underscore.go
# command-line-arguments
./underscore.go:5:2: imported and not used: "math"

An unused import like math in the previous example should eventually be used or removed: blank assignments identify code as a work in progress.

package main

import (
	"fmt"
	_ "math"
)

func main() {
	fmt.Println("This is an example of importing packages in Golang!")
}

Output:

This is an example of importing packages in Golang!

But sometimes it is useful to import a package only for its side effects, without any explicit use. For example, in the article working with SQLite3 in Golang, we import but not use the go-sqlite3 package:

import (
	"database/sql"
	"fmt"
	"log"

	_ "github.com/mattn/go-sqlite3"
)

_ "github.com/mattn/go-sqlite3": If a package is imported with a blank identifier, the package's init function is called:

func init() {
	if driverName != "" {
		sql.Register(driverName, &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", ":memory:")

 

Summary

underscore in front of an import statement means: create package-level variables and execute the init function of that specific packages. And (if applicable) the hierarchy of package-level variables and init functions of packages imported by this package.

The only thing a package can do without being called is create package-level variables (public or private) and run its init function.

Advertisement

 

References

https://go.dev/doc/effective_go#blank_import
https://go.dev/ref/spec#Import_declarations

 

Categories GO

Didn't find what you were looking for? Perform a quick search across GoLinuxCloud

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can either use the comments section or contact me form.

Thank You for your support!!

Leave a Comment