My first steps in learning Go were simple “scripts”; programs compiled and immediately executed by the go
command-line tool. This was a great way to quickly get started; kind of similar to using a REPL. However, I soon wanted to learn how to structure larger programs, create reusable libraries, and use third-party code. In this post, we’ll look at how Go code is organized into packages, the various commands to build and install them, and how to integrate third-party libraries.
Packages
All Go programs and libraries are defined in packages. Packages are named after the final part in their directory path. An import
declaration is used to load a package.
package main
import (
"net/http"
"fmt"
"io/ioutil"
)
func main() {
resp, err := http.Get("http://www.google.com")
if err != nil {
panic(err)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(body))
}
The entry point for every Go program is the main
function in the main
package. This program imports three packages from the Go standard library. A package’s name is used to access its exported interface. In this example, http
is used to access the package’s Get
function.
Creating a Custom Package
The first step in creating a custom package is to create a workspace. A workspace is a directory hierarchy containing three subdirectories:
src
– Go source code organized into packagespkg
– OS and architecture specific compilation artifactsbin
– executable Go programs
When you import a custom package, Go looks for its definition in each workspace listed in the GOPATH
environment variable.
Let’s create a workspace and set the GOPATH
.
% mkdir -p ~/Projects/golang/src
% export GOPATH=~/Projects/golang/
Our custom package will be defined in a src
subdirectory.
~/Projects/golang/src/foo/foo.go
package foo
import (
"fmt"
)
func Bar() {
fmt.Println("bar")
}
% tree golang
golang
└── src
└── foo
└── foo.go
A Go package is named after its directory. Within its directory, it can be implemented in any number of arbitrarily named files. In this example, I chose to name our custom package’s only file after the package.
Importing a Custom Package
With this directory structure in place and the GOPATH
set, we can now create a Go program that can import and use our custom package. This program will also be defined in a src
subdirectory.
~/Projects/golang/src/fooer/fooer.go
package main
import (
"foo"
)
func main() {
foo.Bar()
}
% tree golang
golang
└── src
├── foo
│ └── foo.go
└── fooer
└── fooer.go
Our next step is to build and install this program.
Building Go Code
Build Go code using the go
command-line tool’s build
command.
Building a program creates an executable file in the program’s directory. The executable file is named after its directory.
% pwd
/Users/jared/Projects/golang/src/fooer
% go build
% ls
fooer fooer.go
% ./fooer
bar
Building a custom package results in no build artifacts.
Installing Go Code
Install Go code using the go
command-line tool’s install
command.
Programs are installed in the workspace’s bin
directory.
% pwd
/Users/jared/Projects/golang/src/fooer
% go install
% ls ../../bin
fooer
Custom packages are installed in an OS and architecture specific subdirectory in the workspace’s pkg
directory.
% pwd
/Users/jared/Projects/golang/src/foo
% go install
% ls ../../pkg/darwin_amd64
foo.a
Add $GOPATH/bin
to your PATH
to make executing Go programs easier.
Integrating Third-Party Go Code
Integrate third-party Go code using the go
command-line tool’s get
command. Third-party code is downloaded and installed in the first workspace listed in the GOPATH
.
% pwd
/Users/jared/Projects/golang/src
% go get -v code.google.com/p/freetype-go/freetype
code.google.com/p/freetype-go (download)
code.google.com/p/freetype-go/freetype/raster
code.google.com/p/freetype-go/freetype/truetype
code.google.com/p/freetype-go/freetype
% ls
code.google.com foo fooer
% ls ../pkg/darwin_amd64/
code.google.com foo.a
Moving Beyond Scripts
Every programming language has its own way of organizing code. Knowing where a language is expecting code is a must when moving beyond simple scripts.