Getting Started

Installing Go

Windows

Mac

Linux

running your first program

Now that we have the golang language installed, we are going test that we have installed it correctly by running our very first program! In your workspace directory, $HOME/go, create the directory src/hello. In that directory, create the file hello.go

package main

import "fmt"

func main() {
  fmt.Printf("hello, world\n")
}

build the program with the go tool

$ cd $HOME/go/src/hello
$ go build

there should now be an executable named hello in your current directory. run that executable with

$ ./hello
hello, world

If after running ./hello you see hello, world in your command prompt, congratulations! You have a working install of go and you have written your first go program.

Go basics

lets take a look at the hello.go program that we just wrote.

package main

import "fmt"

func main() {
  fmt.Println("hello, world")
}

Every Go program is made up of packages. Programs start running in package main1. There is also a function in this program called main. The entrypoint into your main package will always be your main function. We also have the expression fmt.Printf("hello, world\n"). This line is taking the package fmt, using the function Println to print the text ~"hello, world"~ to the console.

This may seem like a lot to take in at first, but for now just remember that for every go program you write, you are going to start it with a main package, and a main function.

package main

func main() {
  // code goes here
}

Variables

assignment in go

go use := for assignment instead of = for assignment.

Writing Tests

Characteristics of a Golang test function:2

package main

import "testing"

func TestSum(t *testing.T) {
  total := Sum(5, 5)
  if total != 10 {
    t.Errorf("Sum was incorrect, got: %d, want: %d.", total, 10)
  }
}
  • The first and only parameter needs to be t *testing.T
  • It begins with the word Test followed by a word or phrase starting with a capital letter. (usually the method under test i.e. TestValidateClient)
  • Calls t.Error or t.Fail to indicate a failure (I called t.Errorf to provide more details)
  • t.Log can be used to provide non-failing debug information
  • Must be saved in a file named something_test.go such as: addition_test.go

Generating an HTML coverage report 3

If you use the following two commands you can visualise which parts of your program have been covered by the tests and which statements are lacking:

go test -cover -coverprofile=c.out go tool cover -html=c.out -o coverage.html Then open coverage.html in a web-browser.

Web Scraping

Footnotes

https://blog.alexellis.io/golang-writing-unit-tests/

https://blog.alexellis.io/golang-writing-unit-tests/

https://tour.golang.org/basics/1

file operations

bytes from file

import(
  "os"
  "io/ioutil"
)

func bytesFromFile(filepath string) (data []byte) {
  // Open file for reading
  file, err := os.Open(filepath)
  if err != nil {
    log.Fatal(err)
  }
  defer file.Close()

  data, err = ioutil.ReadAll(file)
  if err != nil {
    log.Fatal(err)
  }

  return
}

chess

Parse pgn file

import(
  "bytes"

  "github.com/notnil/chess"
)

// parse pgn data into a slice of games
func parsePGN(pgnBytes []byte) (games []*chess.Game) {
  b := bytes.NewReader(pgnBytes)
  var err error
  games, err = chess.GamesFromPGN(b)
  if err != nil {
    // handle error
    log.Fatal(err)
  }
  return

}

install dependencies with

go get -u github.com/notnil/chess

.gitignore

# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
# vendor/
.env
.vscode

Dockerfile

############################
# STEP 1 build executable binary
############################
# golang alpine 1.12
FROM golang:alpine as builder

# Install git + SSL ca certificates.
# Git is required for fetching the dependencies.
# Ca-certificates is required to call HTTPS endpoints.
RUN apk update && apk add --no-cache git ca-certificates tzdata && update-ca-certificates

# Create appuser
RUN adduser -D -g '' appuser

WORKDIR $GOPATH/src/gitlab.com/reedrichards/sync-lichess
COPY . .

# Fetch dependencies.
RUN go get -d -v

# Build the binary
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -a -installsuffix cgo -o /go/bin/app .

############################
# STEP 2 build a small image
############################
FROM scratch

# Import from builder.
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /etc/passwd /etc/passwd

# Copy our static executable
COPY --from=builder /go/bin/app /go/bin/app

# Use an unprivileged user.
USER appuser

# Run the hello binary.
ENTRYPOINT ["/go/bin/app"]

docker-compose.yml

version: "3.7"

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - /mnt/data/pgns:/mnt/data/pgns
    env_file: .env