Cheat Sheet

Golang tips and tricks

Install

Manually

Download it from https://golang.org/dl/

Extract it.

tar -xzvf go1.14.4.linux-amd64.tar.gz
sudo mv go /usr/local/

Export env vars.

vim ~/.zshrc
export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export PATH=$GOPATH/bin:$GOROOT/bin:$PATH

Ubuntu (apt)

sudo add-apt-repository ppa:longsleep/golang-backports
sudo apt-get update
sudo apt-get install golang-go

Add to your ~/.bashrc

export GOPATH=$HOME/go
export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin

Libs / Frameworks

Cobra

Async

package main

import (
	"fmt"
	"net/http"
)

func main() {
	// A slice of sample websites
	urls := []string{
		"https://www.easyjet.com/",
		"https://www.skyscanner.de/",
		"https://www.ryanair.com",
		"https://wizzair.com/",
		"https://www.swiss.com/",
	}

	c := make(chan urlStatus)
	for _, url := range urls {
		go checkUrl(url, c)

	}
	result := make([]urlStatus, len(urls))
	for i, _ := range result {
		result[i] = <-c
		if result[i].status {
			fmt.Println(result[i].url, "is up.")
		} else {
			fmt.Println(result[i].url, "is down !!")
		}
	}

}

//checks and prints a message if a website is up or down
func checkUrl(url string, c chan urlStatus) {
	_, err := http.Get(url)
	if err != nil {
		// The website is down
		c <- urlStatus{url, false}
	} else {
		// The website is up
		c <- urlStatus{url, true}
	}
}

type urlStatus struct {
	url    string
	status bool
}

References

https://medium.com/@gauravsingharoy/asynchronous-programming-with-go-546b96cd50c1

Doc

go get golang.org/x/tools/cmd/godoc
godoc -http :8000

Access: http://localhost:8000/pkg/

Go $PATH

echo 'export PATH=$(go env GOPATH)/bin:$PATH' >> ~/.zshrc

Thread safe buffer

package cmd

import (
	"bytes"
	"context"
	"fmt"
	"log"
	"net"
	"os"
	"path/filepath"
	"regexp"
	"sync"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
)

// Thread safe buffer to avoid data races when setting a custom writer
// for the log
type Buffer struct {
	b bytes.Buffer
	m sync.Mutex
}

func (b *Buffer) Read(p []byte) (n int, err error) {
	b.m.Lock()
	defer b.m.Unlock()
	return b.b.Read(p)
}

func (b *Buffer) Write(p []byte) (n int, err error) {
	b.m.Lock()
	defer b.m.Unlock()
	return b.b.Write(p)
}

func (b *Buffer) String() string {
	b.m.Lock()
	defer b.m.Unlock()
	return b.b.String()
}

func TestServe(t *testing.T) {
	tempDir := t.TempDir()
	buf := Buffer{}
	log.SetOutput(&buf)
	defer func() {
		log.SetOutput(os.Stderr)
	}()
	ServeCmd.SetArgs([]string{"--data-dir", tempDir})

	ctx, cancel := context.WithCancel(context.Background())
	go ServeCmd.ExecuteContext(ctx)

	if !waitForServer(":35354") {
		assert.FailNow(t, "server did not start")
	}
	cancel()

	assert.DirExists(t, filepath.Join(tempDir, "db"))
	assert.Regexp(t, regexp.MustCompile("HTTP server listening on: :35354"), buf.String())
	// helps with debugging if test fails
	fmt.Println(buf.String())
}

func waitForServer(addr string) bool {
	for i := 0; i < 40; i++ {
		conn, err := net.Dial("tcp", addr)
		if err == nil {
			conn.Close()
			return true
		}
		time.Sleep(500 * time.Millisecond)
	}

	return false
}

Reference: https://github.com/charmbracelet/charm/blob/953ae05093d15ca955143fcd566dc61306db8d6a/cmd/serve_test.go

Last updated