## Go Crash Course
A quick 1 hour workshop on the basics of Go
*John Nguyen*
## About Me
- Studied Mechatronics Engineering at UWA
- Worked in Mechanical and Process Controls Engineering
- Started working at The Frontier Group in 2015
- Have worked with python, ruby/rails, nodejs, C#
## About Go
[Go](https://golang.org/) is an open source programming language that makes it easy to build simple, reliable, and efficient software.
## Notable Companies Using Go
- Google / Facebook / Yahoo
- Rackspace / Digital Ocean / Heroku
- Shopify / Booking.com / Medium
- IBM / Comcast / Canonical
- Square
- SendGrid / Bitly
- Docker
- Dropbox
## Why Go?
- Simple
- Maintainable
- Scales easily
- Easily generated documentation
- Fast
- Robust tooling
- Single, static binary
- Fast compile times
- Cross platform
- Good community
- Language level concurrency (no callback hell)
- Useful error messages
## Why not Go?
- No generics
- No operator overloading
- Inelegant
- Ugly syntax
- Poor dependency management
- Garbage collector can not be modified easily
- Verbose error handling
## Installation
### OSX
```bash
brew update
brew install go
```
### Linux
Download binary from [https://golang.org/dl/]()
```bash
wget https://storage.googleapis.com/golang/go1.6.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.6.linux-amd64.tar.gz
```
### Web
Visit [https://play.golang.org/]().
## Paths
Add the following to your `.profile`. This will add the binaries to your PATH and also setup your GOPATH environment
```bash
export PATH=$PATH:/usr/local/go/bin/:$HOME/go/bin
export GOPATH=$HOME/go
```
## Tooling
Go comes with its own tool, called `go`. It manages many things, and any missing functionality can be covered with third party tools.
## Go tool
The `go` tool can handle fetching dependencies, running tests, installing binaries, running programs, linting, code formatting, and many others!
```bash
build compile packages and dependencies
clean remove object files
env print Go environment information
fix run go tool fix on packages
fmt run gofmt on package sources
get download and install packages and dependencies
install compile and install packages and dependencies
list list packages
run compile and run Go program
test test packages
tool run specified go tool
version print Go version
vet run go tool vet on packages
```
## Documentation
The Go project cares a lot about documentation, and `golint` enforces clean code that can be parsed for generation of documentation.
The `godoc` tool can parse code to render documentation to stdout.
```bash
$ godoc fmt Formatter
use 'godoc cmd/fmt' for documentation on the fmt command
type Formatter interface {
Format(f State, c rune)
}
Formatter is the interface implemented by values with a custom
formatter. The implementation of Format may call
Sprint(f) or Fprint(f) etc. to generate its output.
```
The `godoc` tool also contains a webserver!
```bash
$ godoc -http=":8082"
$ open http://localhost:8082
```
## Third Party Tools
The third party tooling is very good considering how young Go is. Many of the tools are built in Go, and write to stdout so can be easily parsed and plugged into any editors easily.
A short list of essential third party tools are:
```bash
glide Dependency Management
gocode Allows package inspection for autocompletion
golint Linting for go source code
godef Go to definition
```
## Using Go
The commands `go get`, `go build`, `go run`, and `go test` will probably be your most commonly used commands.
## Cross compilation
To cross compile to a different system architecture, prefix with the relevant environment variables.
Cross compiling for Windows from OSX:
```bash
GOOS=windows GOARCH=amd64 go build main.go
```
## Editors
- [Atom](https://atom.io/) + [go-plus](https://github.com/joefitzgerald/go-plus)
- [Sublime Text](https://www.sublimetext.com/) + [gosublime](https://github.com/DisposaBoy/GoSublime)
- [IntelliJ IDEA Community](https://www.jetbrains.com/idea/download/) + [go-lang-idea-plugin](https://github.com/go-lang-plugin-org/go-lang-idea-plugin)
- [Vim](http://www.vim.org/) + [vim-go](https://github.com/fatih/vim-go)
- [VSCode](https://code.visualstudio.com/) + [vscode-go](https://github.com/Microsoft/vscode-go)
## Program Structure
Go has a very opinionated structure. There are tools to get around this but it is a better idea to follow best practices.
## GOPATH
The GOPATH is where everything is stored. The GOPATH has the following tree:
```bash
$GOPATH
├── bin
└── gocode
└── goimports
└── goreturns
├── pkg
└── darwin_amd64
└── github.com
└── nii236
└── repo-name
└── src
└── github.com
└── nii236
└── repo-name
```
## Packages
These are basically libraries or modules in other languages and is namespaced. Exported identifiers in each package allows users to consume the packages as intended.
Packages are fetched with `go get` and are imported with a fully qualified name and will fetch the HEAD everytime.
```go
import "github.com/exampleUser/exampleRepo"
```
## Vendoring
Since Go 1.5, there has been support for vendoring and dependency management (which allows us to control which versions of packages we fetch).
There have been many third party tools created for this, as the creators of Go do not see it as necessary (as they live in Google's monorepo environment):
- [gb](https://getgb.io/)
- [godep](https://github.com/tools/godep)
- [glide](https://github.com/Masterminds/glide)
## Exported and Unexported Identifiers
If the first letter of a function is a capital, then it is considered an exported identifier and can be accessed from outside the package.
```go
// ExportedFunction is a function that is
// accessible outside of the package
func ExportedFunction() {}
```
If the first letter is lowercase instead, it will be considered private.
```go
func unexportedFunction() {}
```
## Variables
There are a few ways of declaring variables.
```go
var a, b, c int
var i, j, k = true, 2.3, "four"
f, err := os.Open(name)
```
## Types
Go's type system is very simplistic and not easily extensible.
## Data Types
- Integers
- Floats
- Complex Numbers
- Booleans
- Strings
- Constants
## Composite Types
- Arrays
- Slices
- Maps
- Struct
- JSON
- Text and HTML Templates
## Program Flow
[Link](https://play.golang.org/p/iozXXYlnZ6)
Methods to control the program flow are similar to C based languages.
## Conditionals
The `if` statement behaves as expected.
```go
if condition {
// Do something
}
```
You can also assign temporary variables.
```go
if a := something; condition {
// Assign a variable or run a function then do something
}
```
## Select
The select statement lets a goroutine wait on multiple communication operations.
```go
for i := 0; i < 2; i++ {
select {
case msg1 := <- c1:
fmt.Println("received", msg1)
case msg2 := <- c2:
fmt.Println("received", msg2)
}
}
```
## Switch
These statements express conditionals across many branches.
```go
i := 2
fmt.Print("write ", i, " as ")
switch i {
case 1:
fmt.Println("one")
case 2:
fmt.Println("two")
case 3:
fmt.Println("three")
}
```
## Loops
There is only a single reserved word for loops.
```go
for initialization; condition; post {
// Vanilla loop
}
for condition {
// While loop
}
for {
// Infinite loop
}
```
## Range
Iterable objects can also be `range`d over.
```go
a := [1, 2, 3]
for _, v := range a {
fmt.Println(v)
}
```
## Structs
[Link](https://play.golang.org/p/YlrlQIwEO2)
These are a very important part of Go and are worth focusing on.
Structs are typed collections of fields.
Structs are also what enables Go's composition based object oriented programming.
## Struct Example
Here is a struct declaration of a Person containing a Name of type string, and an Age of type int.
```go
type Person struct {
Name string
Age int
}
```
## Instantiating Structs
You refer to struct objects with their memory address when assigning to a variable
```go
func main() {
p := &Person{"John", 29}
fmt.Println(p.Name)
}
```
## Embedding Structs
Go does not provide the typical, type-driven notion of subclassing, but it does have the ability to “borrow” pieces of an implementation by embedding types within a struct or interface.
```go
type Person struct {
Name string
Age int
}
type Developer struct {
Person
Company string
}
type Student struct {
Person
University string
}
```
## Attaching Methods
Use struct pointers only if you need to mutate the object.
```go
func (p Person) sayHello() {
fmt.Println("Hello, I am", p.Name)
}
func (d Developer) sayHello() {
fmt.Println("BeepBoop I am", d.Name)
}
func (d *Developer) changeName(in string) {
d.Name = in
}
```
Run the program.
```go
func main() {
p := &Person{"Andy", 32}
d := &Developer{Person{"John", 29}, "TFG"}
p.sayHello() // Prints "Hello, I am Andy"
d.sayHello() // Prints "BeepBoop I am John"
d.changeName("Johnny")
d.sayHello() // Prints "BeepBoop I am Johnny"
}
```
## Procedures
Go allows both functions and methods with collections of functions passed around as interfaces.
## Functions
Go supports first class functions that do not need to be attached or instantiated from a class/object
Functions in Go can have *multiple return values*
```go
func exampleFunction(varName string) ([]int, error) {
...
}
```
## Anonymous Functions
[Link](https://play.golang.org/p/0tOpD0O1p8)
Go supports anonymous functions.
They can also be used as a return value given the same function signature.
```go
// AnonymousFunc is an anonymous function type
// that can be used as a return value.
type AnonymousFunc func() []int
// Parentfunc simply returns AnonymousFunc.
func Parentfunc() AnonymousFunc {
return func() []int {
return []int{1, 2}
}
}
```
This can be useful for creating wrappers around functions such as building middleware for HTTP handlers.
## Methods
Go also allows you to attach methods to structs
```go
func (s *SomeStruct) mutableMethod(a int) int {
...
}
func (s SomeStruct) immutableMethod(a int) int {
...
}
```
## Interfaces
[Link](https://play.golang.org/p/F6ZCguKs55)
Interfaces in Go provide a way to specify the behavior of an object: if something can do *this*, then it can be used here.
Interfaces are satisfied **implicitly**.
```go
type ExampleInterface interface {
methodOne(in string) string
methodTwo(in []int) (int, error)
}
type First struct { RandomInfo string}
type Second struct { OtherInfo int}
func (s *First) methodOne(a int) string {}
func (s *First) methodTwo(a int) (int, error)
func (s *Second) methodOne(a int) string {}
func (s *Second) methodTwo(a int) (int, error) {}
func satisfied (ex ExampleInterface) {
// Either first or second struct can be used!
}
```
## Hello World
We're going to start with a simple hello world program.
## Hello World Example
[Link](https://play.golang.org/p/I3l_5RKJts)
The below code will get you going:
```go
package main
import "fmt"
func main() {
fmt.Println("Hello, 世界")
}
```
To run it:
```
$ go run main.go
Hello, 世界
```
## Command Line Tools
Let's have a look at parsing command line flags. Go is quite good at building command line tools.
## Command Line Tool Example
```go
func main() {
var cmd string
flag.StringVar(&cmd, "cmd", cmd, `cmd can be either "hello" or "bye"`)
flag.Parse()
switch cmd {
case "hello":
fmt.Println("Hello!")
case "bye":
fmt.Println("Bye!")
default:
flag.Usage()
}
}
```
Lets build it first then run it.
```bash
$ go build main.go
$ ./go-crashcourse
Usage of ./go-crashcourse:
-cmd string
cmd can be either "hello" or "bye"
```
## Concurrency
Go has two main forms of managing concurrency. Goroutines and Channels.
## Go Routines
Go routines are light weight threads that are managed by the Go runtime.
To run a function in a new go routine, just put "go" before the function call.
## Go routine example
[Link](https://play.golang.org/p/W51Ls4Tlsu)
```
// Routines is an example of Go routines.
func Routines() {
go say("let's go!", 3*time.Second)
go say("ho!", 2*time.Second)
go say("hey!", 1*time.Second)
time.Sleep(4 * time.Second)
fmt.Println("Finished")
}
func say(text string, delay time.Duration) {
time.Sleep(delay)
fmt.Println(text)
}
```
## Channels
Channels are typed conduits for synchronization and communication between go routines.
## Go channel example
[Link](https://play.golang.org/p/a8ka_5zoEG)
```go
// Channels is an example of Go channels.
func Channels() {
messages := make(chan string)
go func() { messages <- "ping" }()
msg := <-messages
fmt.Println(msg)
}
```
## Web Client and Server
Go has a very solid standard library and its common in the community to focus on solving most problems with the standard library.
## Client
The net/http package provides an HTTP client.
```
func main() {
r, err := http.Get("http://www.golang.org/")
if err != nil {
log.Fatal(err)
}
if r.StatusCode != http.StatusOK {
log.Fatal(r.Status)
}
io.Copy(os.Stdout, r.Body)
}
```
## Server
The net/http package also provides an HTTP server.
```
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello, web")
})
fmt.Println("Starting server")
err := http.ListenAndServe("localhost:8080", nil)
if err != nil {
log.Fatal(err)
}
}
```
This is a high-performance, DoS-hardened and production-ready web server.
It serves [dl.google.com](http://dl.google.com).
## Server with Templated HTML
We will need to fetch our first dependency for this code.
```bash
go get github.com/gorilla/mux
```
The code below creates a webserver that handles only a single route, `/`, unlike before.
```go
import "github.com/gorilla/mux"
// PartTwo runs a web server with templating
func PartTwo() {
rt := mux.NewRouter().StrictSlash(true)
// Index is described in the slide below
rt.HandleFunc("/", Index)
log.Println("PART TWO: Starting server of localhost:8081")
log.Fatal(http.ListenAndServe(":8081", rt))
}
```
The route handler Index will be handled next.
## Route Handlers
`Index` will be executed when the route `/` is hit.
```go
//Index is the handler for root path
func Index(w http.ResponseWriter, r *http.Request) {
pd := PageData{
Title: "Index Page",
Body: "This is the body of the page",
}
tmpl, err := htmlTemplate(pd)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
return
}
w.Write([]byte(tmpl))
}
```
## Templating
HTML templating is a powerful feature of Go and lets you render data-driven HTML.
As of Go 1.6, blocks are introduced which let you build templates on other templates.
```go
func htmlTemplate(pd PageData) (string, error) {
html := `<HTML>
<head>
<title>
{{.Title}}
</title>
</head>
<body>
{{.Body}}
</body>
`
tmpl, err := template.New("index").Parse(html)
if err != nil {
return "", err
}
var out bytes.Buffer
if err := tmpl.Execute(&out, pd); err != nil {
return "", err
}
return out.String(), nil
}
```
Now we can update our CLI tool and execute our server.
```bash
$ go build
./go-crashcourse -cmd serve2
Running server!
2016/03/04 10:57:19 PART TWO: Starting server of localhost:8081
```
Next we visit [localhost:8081](http://localhost:8081)
```bash
open http://localhost:8081
```
## Testing
Go has a robust standard tooling for table based XUnit type tests. Additional third party libraries are available for more BDD style assertions.
## Testing Example
First we will build the test suite.
```go
package add_test
import (
"testing"
"github.com/nii236/gotraining/testing"
)
var tests = []struct {
in []int
out int
}{
{[]int{1, 2}, 3},
{[]int{-1, 2}, 1},
{[]int{1, 0}, 1},
}
```
Next we will write the test itself.
```go
func TestFunc(t *testing.T) {
for _, tt := range tests {
got := add.Do(tt.in[0], tt.in[1])
expected := tt.out
if got != tt.out {
t.Errorf("Error! Got %d, expected %d", got, expected)
}
}
}
```
Now we will write the code that satisfies the test.
```go
package add
//Do runs a test func given two integers
func Do(a int, b int) int {
return a + b
}
```
And finally we can run the test and see how we go!
```bash
$ go test ./...
? github.com/nii236/gotraining/go-crashcourse [no test files]
? github.com/nii236/gotraining/go-crashcourse/concurrency [no test files]
? github.com/nii236/gotraining/go-crashcourse/hello [no test files]
? github.com/nii236/gotraining/go-crashcourse/serve [no test files]
? github.com/nii236/gotraining/go-crashcourse/structs [no test files]
ok github.com/nii236/gotraining/go-crashcourse/testing 0.005s
```