Way to GO Part I: Getting STarted with the Go Programming Language
By Mark Volkmann, OCI Partner and Principal Software Engineer
November 2018
Introduction
This article is the first in a multi-part series on the Go programming language. It provides an overview of the language and a quick-start guide.
Future articles will cover Go syntax in depth, the Go standard library, concurrency, reflection, solutions to common tasks, modules, testing, and the future of Go.
Overview
Go is an open-source programming language. It runs on Unix-based operating systems (including Linux and macOS) and Windows. Documentation, downloads, and a blog can be found at https://golang.org/.
Go was conceived in 2007 by Robert Griesemer, Rob Pike, and Ken Thompson, all working at Google. About a year later Russ Cox and Ian Taylor joined the team. All of the core team members have made major contributions to important software projects.
Team Member | Major Contributions Before Go |
---|---|
Robert Griesmer | Strongtalk (Smalltalk with optional types), Java Hotspot virtual machine, V8 JavaScript engine |
Rob Pike | Unix, Plan 9 distributed operating system, co-inventor of UTF-8 Unicode encoding |
Ken Thompson | Unix (designed and implemented), B language (led to C), Plan 9, co-inventor of UTF-8 Unicode encoding |
Russ Cox | Plan 9 |
Ian Taylor | GCC compiler, Taylor UUCP |
To get a sense of the timeline for Go, it is useful to see some key dates.
Date | Event |
---|---|
September 2007 | work on Go begins |
November 2009 | Go officially announced |
March 2012 | Go 1.0 released |
February 2016 | Go 1.10 released |
August 2018 | Go 1.11 released |
Many of Go's goals are in comparison to languages like C++ and Java.
Go aims to:
- address software issues at Google
- be simple, indicated by having a small specification and fewer features than most programming languages
- be very easy to read
- enable faster software development
- enable faster build times
- have a less cumbersome type system that provides type inference
- use composition instead of type hierarchies
- provide garbage collection
- be safe in terms of memory utilization
- support concurrent execution and communication
- support parallel computation, taking advantage of multi-core computers
- enable easier dependency analysis
- make it easier to write tools that analyze and process the code
Because simplicity and performance are major goals, many features found in other programming languages are not present in Go. These include classes, inheritance, annotations, exceptions, and generic types. Generic types are being considered for Go 2.0.
Go is compiled to platform-specific machine code, not bytecode for a virtual machine that must be interpreted at runtime.
Go occupies a space between languages that are often used for systems programming (C, C++, and Rust) and scripting languages (JavaScript, Perl, Python, and Ruby).
Currently the most common uses for Go are DevOps tooling and server-side web application development, including implementing REST services.
The primary Go compiler and runtime are implemented in a combination of Go and assembly.
Go Lineage
Many previous programming languages inspired the design of Go.
Go's characteristics at a glance include:
- a relatively small language that is easy to learn (the May 9, 2018 spec is only 78 pages)
- statically typed, which catches many errors at compile-time
- type inference
- garbage collection of variables that are no longer reachable
- Unicode support
- concurrency with lightweight threads called "goroutines"
- communication between goroutines using "channels"
- object-oriented programming through structs and other types with methods
- a standard library that supports many common operations including text processing, I/O, networking, cryptography, and more
- compiles quickly to native executables and libraries, not code that requires a virtual machine
- for applications, produces a single file to be deployed which is easier than working with archives that contain many files and require additional software to run, such as Java WAR files and servers such as Tomcat
- high performance
Not Included
Go purposely omits many features found in other programming languages in order to arrive at a simpler programming language. These include:
- ternary operator
- implicit type coercions
- default parameters
- constructors and destructors
- type inheritance
- operator overloading
- pointer arithmetic
- exceptions
- generics
- macros
- annotations
- thread-local storage
Reasons to Avoid Go
Reasons some developers choose not to use Go include:
- Some developers dislike the community standards for Go, such as using gofmt to format code.
- Go does not currently support generic types, which precludes some aspects of functional programming.
Additional reasons related to systems programming include:
- Some developers feel that C and C++ libraries are currently more mature than Go libraries.
- Currently it is easier to find developers that have C and C++ experience than to find Go developers.
- Go provides garbage collection and does not allow control of memory allocation/deallocation that is needed for real-time guarantees.
- Go does not support pointer arithmetic which is needed for some types of applications.
Important Environment Variables
GOPATH
- Set this to the current workspace directory where source files are located. Change this when switching workspaces. When not set,
$HOME/go
is used. GOBIN
- Set this to the directory where packages should be installed. When not set, packages are installed in
$GOPATH/bin
. GOARCH
- Set this to the target architecture to use when compiling. When not set, the current architecture is assumed.
GOOS
- Set this to the operating system to be targeted by the Go compiler. When not set, the current operating system is assumed.
Companies Using Go
A long list of companies currently using Go is maintained at https://github.com/golang/go/wiki/GoUsers.
The list includes:
Adobe, AgileBits (1Password), BBC, Bitbucket, CircleCI, CloudFlare, Cloud Foundry, Comcast, Dell, DigitalOcean, Docker, Dropbox, eBay, Facebook, General Electric, GitHub, GitLab, Google, Heroku, Honeywell, IBM, Intel, Lyft, Medium, Mesosphere, MongoDB, Mozilla, Netflix, New York Times, Oracle, Pinterest, Pivotal, Rackspace, Reddit, Riot Games, Shutterfly, Slack, Square, Stripe, Tumblr, Twitch, Twitter, Uber, VMware, and Yahoo
Implemented in Go
The following applications and libraries are some of the more popular ones that have been implemented in Go.
- Bolt https://github.com/boltdb/bolt
- "An embedded key/value database for Go."
- Buffalo https://gobuffalo.io/en
- "Buffalo is a Go web development eco-system. Designed to make the life of a Go web developer easier.
Buffalo starts by generating a web project for you that already has everything from front-end (JavaScript, SCSS, etc...) to back-end (database, routing, etc...) already hooked up and ready to run. From there it provides easy APIs to build your web application quickly in Go." - CockroachDB https://www.cockroachlabs.com
- "the open source, cloud-native SQL database"
- Docker https://www.docker.com/
- assembles container-based systems (open source version is now called "Moby")
- InfluxDB https://github.com/influxdata/influxdb
- scalable datastore for metrics, events, and real-time analytics
- Istio https://istio.io/
- connect, secure, control, and observe services
- Kubernetes http://kubernetes.io
- "an open-source system for automating deployment, scaling, and management of containerized applications"
- mongo-go-driver https://github.com/mongodb/mongo-go-driver
- "MongoDB Driver for Go"
- Revel https://github.com/revel/revel
- full-stack web framework
- Testify https://github.com/stretchr/testify
- "A toolkit with common assertions and mocks that plays nicely with the standard library"
Alternative Go Implementations
Besides the primary Go implementation at https://golang.org/, there are several alternative implementations. These include:
- gccgo https://gcc.gnu.org/onlinedocs/gccgo/
- GNU compiler for Go
- GopherJS https://github.com/gopherjs/gopherjs
- This compiles Go to JavaScript.
- llgo https://github.com/go-llvm/llgo
- LLVM-based compiler for Go
- WASM (Web Assembly)
- Early support is available now, but it is not yet ready for serious use. See https://react-etc.net/entry/webassembly-support-lands-in-go-language-golang-wasm-js
Getting Started
Let's walk through the steps to create a Go application. If you don't already have a GitHub (https://github.com), Bitbucket (https://bitbucket.org), or GitLab (https://gitlab.com) account, I recommend creating one now so you can experience publishing an app.
This article uses the term "terminal" to refer to a Windows Command Prompt or a Linux/Mac Terminal window.
The support for "modules" added in Go 1.11 is considered experimental and will not be used here. When using modules, some of the steps described in this section are performed in a different way.
Install Go
One way to install Go is to browse https://golang.org/dl/, find a binary release for your system, and follow the instructions. If you are using a Mac and have Homebrew (https://brew.sh/) installed, you can instead run brew install go
. To verify that Go is installed, open a terminal and enter go version
which should output the version of Go you have installed.
In Unix and macOS, Go is installed in the /usr/local/go
directory. The src
subdirectory contains the source code for the standard library packages.
Create a Workspace
Go projects live in a workspace, which is home to one or more packages. A package is defined by one or more .go
source files that reside in the same directory within a workspace.
A workspace can host any number of projects. It's not uncommon to have a single workspace that hosts every project on the computer. The environment variable GOPATH
must be set to point to the top directory of the workspace currently being used.
Create a go
directory in your home directory. Set the GOPATH
environment variable to point to this directory.
One way to see the current value of GOPATH
is to enter go env GOPATH
. This works on any platform, unlike entering echo $GOPATH
which only works on UNIX-like systems.
Create First App
Create a src
directory inside your go
directory.
Packages and applications contributed by the community (not in the standard library) must be installed. This is typically done using go get package-url
where package-url
excludes the https://
prefix.
Packages are installed under $GOPATH/src
in a subdirectory that corresponds to the package URL. It does this regardless of the directory from which go get
is run.
For example, go get github.com/julienschmidt/httprouter
downloads the.go
files that implement the package to $GOPATH/src/github.com/julienschmidt/httprouter
and installs the package. Using the package URL avoids path/directory conflicts.
The go get
command also builds the package and places its object file under the $GOPATH/pkg
directory. In the case of httprouter, this creates httprouter.a
in the $GOPATH/pkg/{platform}/github.com/julienschmidt
directory. An example value for {platform}
on a Mac is darwin_amd64
.
It is recommended that you use the same approach for placing your own packages in a workspace to avoid name collisions and prepare for publishing the code in the future.
Note that there can be many local version control repositories under the src
directory. It's not necessary for the GOPATH
directory to correspond to a single repository.
Determine your preferred repository domain, such as github.com
, and your repository username, such as mvolkmann
. Create the directory {repo-domain}/{repo-username}/{name}
inside your src
directory where {name}
is the name of the application or package you wish to create. For an application named hello
, I would use github.com/mvolkmann/hello
.
Create the file main.go
inside this directory.
Go source files begin with a package
statement. This is followed by imports of other packages if any are needed. The imports are followed by top-level declarations of package-scoped constants, variables, functions, types, and methods. Each of these will be described in detail in the next article in the series.
Each application has a single function named main
that must be in a package named main
. This is the starting point of the application. The one file that defines the main
function is often named main.go
, but that is not required.
The primary way of writing output to the standard output stream (stdout) is to use functions in the standard library package fmt
.
Add the following to main.go
.
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
As you experiment with various features of Go, you'll likely want to create additional directories like hello
that each contain a main.go
file.
Run First App
Open a terminal and cd to the directory containing main.go
. Enter go run main.go
to run the app. This should output "Hello, World!".
Consider creating an alias for this, because you'll be running this command often. My alias name is grm
which is short for "go run main".
Build First App
To build an executable for this application, enter go build
while in the directory containing the file that defines the main
function. This will create an executable file in the current directory that has the same name as the directory, hello
in this case. In Windows this file will have a .exe
file extension.
To run the application, enter ./hello
, or in Windows just hello
.
Go executables are statically linked, which means they can be run without any other supporting files. They can be copied to a machine with the same architecture and be run without installing anything else.
Install First App
When Go installs an app, it creates the executable in the bin
subdirectory of the current workspace. If this directory doesn't exist, it is created. It is convenient to have this directory included in your PATH
environment variable so these executables can be run from anywhere by just entering their names. Go ahead and add $GOPATH/bin
to your PATH
environment variable now.
To install the application, enter go install
while in the directory containing the file that defines the main
function. Assuming that your PATH
environment variable is set correctly, you can now run the application by just entering hello
regardless of your current working directory.
To delete the installed executable, enter go clean -i
while in the directory containing the file that defines the main
function..
Create First Package
Non-trivial Go applications divide their code into several packages. A package is a collection of .go
files in the same directory that all begin with the same package
statement. By convention, the directory name of a package should match the package name. We will cover packages in more detail later.
To keep things simple so we can focus on the mechanics of Go, we will create a package that just provides a couple of basic functions. The first will return the largest number in a collection of numbers. The second will return the average of a collection of numbers.
Create the directory $GOPATH/src/github.com/mvolkmann/statistics
, substituting your repo domain and username. Create the files maximum.go
and average.go
in this directory. We could define both functions in the same file, but we are using two files to show that a package can be defined by multiple source files. Note that both files must begin with the same package
statement.
The code below contains several comments to explain certain Go features. These will be described in more detail in the next article in the series.
Add the following to maximum.go
.
package statistics
// Max returns the maximum of a "slice" of float64 values.
// For now think of a slice as being like an array.
// Functions are only available to be used in other packages
// if they are "exported" which is indicated by
// starting their names with an uppercase letter.
// The type of the parameter "numbers" is a "slice"
// of double-precision floating point numbers.
// The return type follows the parameter list.
func Max(numbers []float64) float64 {
if len(numbers) == 0 {
return 0
}
// The := operator declares the variable on the left
// and initializes it to the value on the right.
max := numbers[0]
// "range" is a keyword that is used to iterate over many kinds of sequences,
// one of which is a slice. In each iteration it returns two values.
// For slices it returns an index and the value at that index.
// In this example we do not need the index. That is indicated by
// placing it in the "blank identifier" represented by an underscore.
for _, number := range numbers {
if number > max {
max = number
}
}
return max
}
Add the following to average.go
.
package statistics
// This function is for internal use by this package
// so it is not exported (name starts lowercase).
func sum(numbers []float64) float64 {
result := 0.0
for _, number := range numbers {
result += number
}
return result
}
// Avg returns the average of slice of float64 values.
func Avg(numbers []float64) float64 {
if len(numbers) == 0 {
return 0
}
// Go is very picky about types!
// The "len" function returns an int.
// We cannot divide a float64 by an int,
// so we must cast the int to float64.
return sum(numbers) / float64(len(numbers))
}
Run go install
from the statistics
package directory to create the file statistics.a
in the directory $GOPATH/pkg/{platform}/github.com/mvolkmann
directory.
If any of these directories below $GOPATH
does not yet exist, they will be created. The file statistics.a
is an object file. When other packages that use this package are installed, this file is used rather than compiling the code again to speed up build times.
Add Tests
Let's add tests to the "statistics" package.
The VS Code Go extension provides the "Go: Generate Unit Tests For Package" command that does what its name implies. It generates files with names that end in _test.go
for each .go
file in the current package. You could of course manually create these files.
Here is what it generates in maximum_test.go
:
package statistics
import "testing"
func TestMax(t *testing.T) {
type args struct {
numbers []float64
}
tests := []struct {
name string
args args
want float64
}{
//TODO: Add some test data here.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Max(tt.args.numbers); got != tt.want {
t.Errorf("Max() = %v, want %v", got, tt.want)
}
})
}
}
This uses the standard library package testing
.
Each test function must have a name that begins with Test
and takes a pointer to a testing.T
object. These functions create a slice of structs called tests
that each describe a test assertion. Each test assertion has a name, a set of arguments to be passed to the function being tested (called "args"), and the expected result (called "want"). The loop that follows iterates through the "tests" and fails if for any assertion the actual value returned from the function being tested does not match the "want" value.
All that is left for us to do is replace the TODO
comment with some test data.
Replace the TODO
comment with the following:
{"empty slice", args{[]float64{}}, 0.0},
{"single value", args{[]float64{3.1}}, 3.1},
{"multiple values", args{[]float64{3.1, 7.2, 5.0}}, 7.2},
The tests in average_test.go
are a little tricker.
When comparing computed floating point values, we need to test whether they are "close," not exact, due to the well-known issue of representing floating point numbers in binary.
We can import the standard library package "math" in the test file and add a function like this:
func close(n1 float64, n2 float64) bool {
return math.Abs(n1-n2) < 1e-9
}
Then we can change got != tt.want
in the tests to !close(got, tt.want)
.
The resulting average_test.go
file contains the following:
package statistics
// Note how multiple packages can be imported
// in a single "import" statement.
import (
"math"
"testing"
)
func close(n1 float64, n2 float64) bool {
return math.Abs(n1-n2) < 1e-9
}
func Test_sum(t *testing.T) {
type args struct {
numbers []float64
}
tests := []struct {
name string
args args
want float64
}{
{"empty slice", args{[]float64{}}, 0.0},
{"single value", args{[]float64{3.1}}, 3.1},
{"multiple values", args{[]float64{3.1, 7.2, 5.0}}, 15.3},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := sum(tt.args.numbers); !close(got, tt.want) {
t.Errorf("sum() = %v, want %v", got, tt.want)
}
})
}
}
func TestAvg(t *testing.T) {
type args struct {
numbers []float64
}
tests := []struct {
name string
args args
want float64
}{
{"empty slice", args{[]float64{}}, 0.0},
{"single value", args{[]float64{3.1}}, 3.1},
{"multiple values", args{[]float64{3.1, 7.2, 5.0}}, 5.1},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Avg(tt.args.numbers); !close(got, tt.want) {
t.Errorf("Avg() = %v, want %v", got, tt.want)
}
})
}
}
Note that this includes tests for both exported and non-exported functions.
To run the tests, cd to the statistics
directory and enter go test
. Try changing an assertion so it fails and run the tests again to see failing output. The output includes the test function name, file name, assertion name, and line number of each failure.
When using VS Code with the Go extension, the Command Palette contains additional commands whose names begin with "Go:". Several of these are related to testing including "Generate Unit Tests For File," "Generate Unit Tests For Package," "Test Function At Cursor," "Test File," "Test Package," and "Test All Packages In Workspace."
If the tests in a file require setup before any of its test functions run or teardown after all of its test functions run, define a TestMain
function. For example,
func TestMain(m *testing.M) {
// Do setup here.
// Run all the test functions in this file.
result := m.Run()
// Do teardown here.
// This MUST be done to complete the tests in this file!
os.Exit(result)
}
To run tests for multiple packages in the current workspace, cd to $GOPATH
and enter go test
followed by the import paths of all the packages to be tested.
Wildcards in test import paths are not supported. However, using ...
in place of the final directory name in the path runs all tests in the specified directory and subdirectories. For example, go test ./..
runs all tests in the current package directory and in those in subdirectories.
When go test
is given package import paths to run, it remembers (caches) successful tests. Later when a package is tested again in this way, if its last test was successful and there have been no related code changes the tests are skipped to save time. When this happens "(cached)" will appear after the test in place of the elapsed time.
Note that tests are never skipped in this way when go test
is run without listing package names or run from inside a package directory.
Test Coverage
Go has built-in test coverage. To merely see the percentage of code in the current package that is covered by tests, enter go test -cover
.
To capture test coverage details in a file, enter go test -coverprofile=cover.out
.
To open an HTML presentation of this data in the default browser, enter go tool cover -html=cover.out
. For example, here is a screenshot of the result if we comment out the assertion for an empty slice in the TestAvg
function.
The dropdown menu in the upper left can be used to view coverage for a different source file. It includes the percentage of coverage for each file.
Example Tests
The Go test tool also supports a form of test called "examples." These test function names must begin with "Example." They write to stdout and provide a special comment that describes the expected output. Examples fail if the expected output is not produced.
Here is an example of such a test for our Maximum
function that can be added to $GOPATH/src/github.com/mvolkmann/statistics/maximum_test.go
.
func ExampleMax() {
fmt.Println(Max([]float64{}))
fmt.Println(Max([]float64{3.1}))
fmt.Println(Max([]float64{3.1, 7.2, 5.0}))
// Output:
// 0
// 3.1
// 7.2
}
Test coverage for example tests is not currently tracked accurately. For example, failing to test the empty slice case of the Max
function reports that none of the code in the Max
function is covered.
While example tests are a kind of test, their main purpose is to provide example code for using a package in generated documentation, which is covered next.
Another form of test is benchmark tests.
Benchmark test functions have names that begin with "Bench." They have a single parameter of type *testing.B
. This parameter is a pointer to a struct with a field named N
that holds the number of times to run the function being benchmarked.
For example,
func BenchmarkMax(b *testing.B) {
values := []float64{3.1, 7.2, 5.0}
for i := 0; i < b.N; i++ {
Max(values)
}
}
To run all the benchmark tests in the current directory, go test -bench=.
. This outputs how long it took to run each benchmarked function a large number of times.
Assuming the functions being tested do not trigger errors, these tests never fail. They just provide information that can indicate performance issues.
The primary way in which benchmark tests are used is to run them before making code changes, save the results, make code changes, run the benchmark tests again, and compare these results to the previous results to verify that the changes did not cause a performance regression.
For more detail on Go tests, see https://golang.org/pkg/testing/.
Generate Documentation
The go doc
and godoc
tools generates package documentation. They parse .go
source files, looking for comments that follow certain conventions.
To add documentation to any package-level declaration (package, type, constant, variable, function, or method), add a comment directly before it. Godoc will render the comment to the right of the item to which it pertains.
Paragraphs must be separated by blank lines.
When HTML documentation is generated, URLs in documentation comments are converted to hyperlinks.
Text to be output in a monospace font, such as code examples, should be indented farther than the other comment text.
The comment preceding a package statement can appear in any source file for the package. If the package has more than one source file, this comment does not need to be repeated in each of them.
One approach for multi-file packages is to create a file named doc.go
that contains only the package comment followed by a package
statement.
Package comments should begin with the name of the package, followed by a description of its purpose.
Create the file doc.go
in the statistics
directory with the following content:
// statistics provides functions that compute statistical values
// for a slice of float64 values.
package statistics
We already have good comments above the exported functions in average.go
and maximum.go
.
The go doc
command provides a quick overview of a package. For an overview of the statistics
package, enter go doc
while in the statistics
directory or go doc statistics
if in another directory.
This produces the following output:
package statistics // import "github.com/mvolkmann/statistics"
statistics provides functions that compute statistical values for a slice of
float64 values.
func Avg(numbers []float64) float64
func Max(numbers []float64) float64
This tells us how to import the package and the purpose of the package, but it does not output the function comments.
The godoc
command produces more detailed documentation. Enter godoc
followed by a package path.
This can also be used to view documentation on standard library packages.
In addition to specifying a package name, a name the package exports can be specified to limit the output to just that documentation. For example, the standard library package "strings" exports a "Join" function. To see its documentation, enter godoc strings Join
.
To see documentation for our "statistics" package, enter godoc github.com/mvolkmann/statistics
, which produces the following output:
PACKAGE DOCUMENTATION
package statistics
import "github.com/mvolkmann/statistics"
statistics provides functions that compute statistical values for a
slice of float64 values.
FUNCTIONS
func Avg(numbers []float64) float64
Avg returns the average of slice of float64 values.
func Max(numbers []float64) float64
Max returns the maximum of slice of float64 values.
To browse an HTML version of this documentation, enter godoc -http=:1234
where 1234 is a port number. Any available, non-privileged port can be used.
Browse localhost:1234 to see a local version of all the official Go documentation combined with documentation for your packages.
To see documentation for the statistics
package, press the "Packages" button at the top, search the page for "statistics," and click that link. The following will be displayed:
To see example code for the Max
function and its output, expand the "Example" section at the bottom of its documentation.
Use Package
Now we're ready to use the statistics package in our application.
Edit $GOPATH/src/github.com/mvolkmann/hello/main.go
. Change the import statement to the following.
import (
"fmt"
"github.com/mvolkmann/statistics"
)
Add the following to the main
function.
numbers := []float64{1, 2, 7}
fmt.Println("maximum =", statistics.Max(numbers))
fmt.Println("average =", statistics.Avg(numbers))
Run the code by entering go run main.go
from the hello
directory and verify that the correct output is produced.
Community packages
Using community packages is similar to using our own custom packages. They just need to be installed.
For example, to install the package "github.com/ttacon/chalk", enter go get github.com/ttacon/chalk
.
This package is similar to the Node package "chalk" which outputs ANSI escape sequences to color and style text that is written to the terminal. Installing this will add the source files for the package in the appropriate directory below $GOPATH/src
and install it by building a .a
object file under $GOPATH/pkg
.
To use this package in our "hello" app, edit main.go
, add an import for this package, and add the following in the main
function.
fmt.Printf("%s%s%s\n", chalk.Magenta, "So pretty!", chalk.Reset)
red := chalk.Red.Color
yellow := chalk.Yellow.Color
blue := chalk.Blue.Color
fmt.Println(red("Hello,"), yellow("my name is"), blue("Mark!"), chalk.Reset)
Publish Package or App
Publishing a Go package or application is easy!
- Select a version control host such as GitHub, BitBucket, or GitLab.
- Create a repository there.
- Clone the repository.
- Commit and push the source files to it.
- Add a semantic version tag, such as
v1.2.3
, where 1 is the major version, 2 is the minor version, and 3 is the patch version.
The go get
command can now be used to retrieve a specific version of the package.
For more detail on publishing, see https://github.com/golang/go/wiki/PackagePublishing.
Conclusion
Learning Go has been interesting and fun for me! I hope you enjoy it also.
Look for additional articles in this series early in 2019 at https://objectcomputing.com/resources/publications/sett. These will prepare you to put your Go knowledge to use in real world applications.
Thanks to Charles Sharp for his detailed review of this article!
Resources
There are many Go resources on the web, but the following are some of the most important. They are listed roughly in the order they should be visited.
- "A Tour of Go": https://tour.golang.org/
- built on "The Go Playground"
- can use on web or download and run locally
- when used on web
- uploads code to golang.org servers, builds it, runs it, and displays result
- uses latest stable version of Go
- "The Go Playground": https://play.golang.org/
- can enter and test code online
- can share code with others, but not sure how long code is retained
- "The Go Play Space" at https://goplay.space/
- a better alternative to "The Go Playground"
- provides syntax highlighting, configurable indentation, use of Fira Code font, auto-indenting, help on double-click, ability to highlight lines (useful when sharing snippets), and more
- "How to Write Go Code": https://golang.org/doc/code.html
- "demonstrates the development of a simple Go package and introduces the go tool"
- "Effective Go": https://golang.org/doc/effective_go.html
- free, online "book"
- GopherCon 2015: Robert Griesemer - The Evolution of Go: https://www.youtube.com/watch?v=0ReKdcpNyQg
- "The Go Programming Language Specification": https://golang.org/ref/spec
- golang.org articles: https://golang.org/doc/#articles
- a curated list of articles about Go
- GoDoc: https://godoc.org
- "hosts documentation for Go packages on Bitbucket, GitHub, Launchpad and Google Project Hosting"
- can search for packages by import path or keyword and see their documentation
- Awesome Go: https://awesome-go.com
- "A curated list of awesome Go frameworks, libraries and software"
- Go Walkthrough: https://medium.com/go-walkthrough
- "A series of walkthroughs to help you understand the Go standard library better"
- seems to have stopped after seven walkthroughs, with the last in September 2016
- Gophers Slack workspace: https://invite.slack.golangbridge.org/
- sponsored by Ardan Labs
- has a #newbies channel
- #go-nuts channel on the Freenode IRC server
- for real-time help
- Go Nuts mailing list: https://groups.google.com/forum/#!forum/golang-nuts
- official mailing list
- golang-announce mailing list: https://groups.google.com/forum/#!forum/golang-announce
- subscribe to receive emails about major events in Go, such as new releases
- "Go Time" podcast: https://changelog.com/gotime
- Golang Weekly: https://golangweekly.com/
- "a weekly newsletter about the Go programming language"
Software Engineering Tech Trends (SETT) is a regular publication featuring emerging trends in software engineering.