In this blog we will look at Packages in Go language, and how to import and use packages.
This blog is part of the tutorial series – Learn Go, in which we will learn about Go language step by step.
Table of Contents
- Go programs are made of Packages, and Packages contains Go source files.
- In a very simplistic terms, Packages are nothing but a way of organizing your code within some directories, and controlling what code is exposed to other packages. Refer to example below, where the project directory contains many packages – common / http / icmp / parse / tcp.
├── common │ ├── CommonUtil.go │ └── NetworkInterfaceUtil.go ├── http │ └── HTTPRequestPinger.go ├── icmp │ ├── ICMPPinger.go │ ├── MessageReciever.go │ ├── MessageSender.go │ └── ip-address.txt ├── parse │ └── ElasticSearchParser.go └── tcp └── TCPConnectionPinger.go
As you can see above, it has helped in code organization of multiple Go Source files
- Package definition should be the first line of any Go program. e.g.
The Go file containing above package definition should be placed in a directory with name
- For those who are familiar with
Javapackages, there is one subtle difference.
Suppose your source file is within a nested packages.
com └── learn └── demo └── hello.go
If this was in
Java, the package name would have been written as
Go, the package name is just the current directory where the file is
2.0 Importing Packages
First question first – Why would you need to import packages?
A simple answer is that we import packages to use the functions/identifiers, etc that have been defined in that package.
e.g Import the
fmt package that provides formatted I/O functions in GoLang.
2.1 Simplest import (import just 1 package)
Now once we have imported the package, we would want to use some functions, etc., from the package.
E.g Suppose we wanted to use a function
Println(), that is defined in package
fmt. How do we call the function?
The function can be referenced using the package name. e.g.
2.2 Importing multiple packages
First option, is to write each import in a new line, as below
import "fmt" import "math/rand" import "strings"
OR another better option is to use a factored import statement (within paranthesis)
import ( "fmt" "math/rand" "strings" )
As before, we can still reference the imported packages with the package name (as shown in earlier example). E.g.
fmt.Println(...) rand.Int() strings.toLower(...)
An important this to note is that when we import a package we use the full path of the package. e.g math/rand
But when refer to an imported package in our code, we just use the actual package name. e.g rand.Int()
2.3 Importing packages using aliases
import ( r "math/rand" f "custom/file/io" s "custom/socket/io" )
Of course you might have a question, on why should we use aliases?
Two common situations where i think package aliasing helps are
- Package names are big, and we want to refer it using short alias
- Duplicate package names.
E.g 2 different io package was imported in above example.
Since we have used aliases, so now we should use the package alias instead of the package name to reference the functions inside the package.
r.Int() s.SomeFunction(...) f.AnotherFunction(...)
2.4 Importing packages using Dot notation
import ( . "fmt" )
This is mostly used when – you want to refer to package functions/constructs without using any package alias.
Reference the imported packages without any package name or alias.
E.g. since in above example we have imported package “fmt” using dot notation, we can refer to it’s function as if it was defined within the current Go source file.
// No need to call as
fmt.Println()// We can directly call the function as below. Println(...)
Note: Unused imports are NOT allowed in GO
E.g if you import “math/rand” in “hello.go” but never used it, on compilation you will get this error – ./hello.go:4:8: imported and not used: “math/rand”
One workaround is possible – if you still want to keep the import but not use it, is by prefixing it with _ alias. e.g
import _ math/rand