Alternate Ways of Importing Packages

There a couple more ways of importing packages in addition to the widely used method of using the import keyword and package name as a string literal.

Let's take a look at these different ways, following examples of each. Code for each example is available here.

  • import . "fmt" - Allows direct access to the contents of fmt.

  • import foo "fmt" - Creates an alias foo for fmt.

  • import _ "fmt" - Supresses compiler warnings if content from the package isn't used, executes init() functions if there are any. Package content is inaccessible, only init functions are included.

Dot Package Import

Preceeding the string literal of a package name with a period allows direct access to the package contents.

dot_package_import.go

package main

import (  
        "fmt"
        . "math"
)

func main() {  
        fmt.Println("Pi is ", Pi)
        fmt.Println("The square root of Pi is ", SqrtPi)
}

This example conveys simplicity. The contents of the math package that are used, Pi and SqrtPi, accurately describe its contents. To me, preceeding them with math. is redundant.

Alias Package Import

Preceeding the string literal of a package name with an alias is self explanatory.

alias_package_import.go

package main

import format "fmt"

func main() {  
        format.Println("Hello, World!")
}

This is useful in two ways. Consider the well known markdown parser blackfriday by RussRoss:

  • Readability - giving it a more semantic name would be helpful (since blackfriday is well known, it might not be so helpful in this sense). However, there's a point to be made for parser.MarkdownBasic(input) over blackfriday.(MarkdownBasic).

    A package with a long or arbitrary name can surely benefit from an alias.

  • Organization - if I wanted to replace the package with my own implementation (given that the naming of the functions, constants, etc. are the same), I would only need to modify the string literal.

Blank Identifier Package Import

Placing a blank identifier before the string literal will execute the init functions of a package if there are any. For more on inititalization, this thread on Stackoverflow was helpful. I would like to make a post on this later...

There's not really a practical example at the moment, but I'd rather share this post first and flesh one out later.

blank_identifier_import.go

import (  
       "image"
       _ "image/gif"
       _ "image/png"
       _ "image/jpeg"
        )

This example depicts an import clause designed to process images without the need for any of the package contents.

The init functions of the three packages register their particular image format with the image package. Credits to Mark Summerfield's Programming in Go for this example.

Content of packages which include a blank identifier in their import statement is not accessible. They are strictly limited to the execution of their init function(s).

Here is the init function that would be executed for image/png, located in the source:
http://golang.org/src/pkg/image/png/reader.go

func init() {  
        image.RegisterFormat("png", pngHeader, Decode, DecodeConfig)
}

Notes

  • Package Conflicts

    One important feature of referring to package content by preceeding them with their package name is that it reduces the possibility of naming conflicts.

    It's possible to import both a custom package that contains a function named Printf() and fmt in a program without any issues. However, if the dot import package method is used to import both packages, there will be a conflict. This is because the packages are in the same namespace; the Printf() functions will have a naming conflict.

  • Blank Identifier Package Import

    Although using the blank identifier import package method doesn't allow access to the remaining package content, it is possible to import the same package again without any error (Packages are still only imported once). This is perfectly valid:

    import (
           _ "fmt"
           "fmt"
            )
    

    Since the initialization functions are executed in the second import of "fmt", this does seem redundant, but still possible!

  • A package cannot import itself directly or indirectly.

  • It is possible to have more than one init function in a package.

Helpful Resources