# golang reference
# download - https://go.dev/dl/
# download and install - https://go.dev/doc/install
# to install the toolset, download and run the installer from golang.org/dl
# tutorial: get started with go - https://go.dev/doc/tutorial/getting-started
# tutorial: create a go module - https://go.dev/doc/tutorial/create-module
# tutorial: using go modules - https://go.dev/blog/using-go-modules
# tutorial: gonum matrix -
# https://pkg.go.dev/gonum.org/v1/gonum/mat?utm_source=godoc
# tutorial: The gonum numerical computing packages -
# https://www.gonum.org/post/intro_to_gonum/
# data format: https://pkg.go.dev/fmt#Scanf
# awesome go: https://awesome-go.com/
# go-to guide: https://yourbasic.org/golang/#cheat-sheets
# staticcheck: https://staticcheck.dev/docs/getting-started/
# math/bits: https://pkg.go.dev/math/bits
# lean go with tests: https://quii.gitbook.io/learn-go-with-tests/
# go tutorials & examples: https://gosamples.dev/

# online resources:
Tutorials: https://go.dev/doc/tutorial/
The Official Go Website
The Go Tour

go version                      # print version
go help                         # list of tools
go help doc                     # documentation tool
go help list                    # list tool
go env                          # environment variables
go env GOPROXY GOROOT GOCACHE   # specific environment variables
go env --json | jq .
go env --json | jq -r '.GOPROXY'

# GOPATH /* path for installed executable binaries - $GOPATH/bin */
To find out where $GOPATH is, run
$ go env GOPATH
/home/user/go   /* default GOPATH */
To change the default GOPATH, edit .bashrc
export GOPATH="$HOME/.gopath"   /* change GOPATH */
export PATH=$GOPATH/bin:$PATH   /* add GOPATH to PATH */
$ go env GOPATH                 /* source .bashrc */
/home/user/.gopath

# installing program/package with go install
The 'go install' command behaves almost identically to 'go build', but instead of
leaving the executable in the current directory, or a directory specified by the -o
flag, it places the executable into the '$GOPATH/bin' directory.

To find where your $GOPATH directory is located, run the following command:
$ go env GOPATH

The output you receive will vary, but the default is the 'go' directory inside of
your $HOME directory: /home/user/go

Since 'go install' will place generated executables into a sub-directory of '$GOPATH'
named 'bin', this directory must be added to the '$PATH' environment variable.

With the '$GOPATH/bin' directory set up, move back to your project source directory and
run the install command:
$ go install

This will build your binary and place it in '$GOPATH/bin'. To test this, run the
following:
$ ls $GOPATH/bin    /* list the contents of $GOPATH/bin */

# formating program in golang
go fmt filename.go

# list files whose formatting differs from gofmt's
gofmt -l
# code format: simplify and write result to (source) file
gofmt -s -w
# 'gofmt' plus fix imports and write result to (source) file
goimports -w

# mechanical source transformation
# rewrite code
gofmt -r ...
# rewrite rule: pattern -> replacement
# [pattern] & [replacement] must be valid go expressions
gofmt -r 'bytes.Compare(a, b) == 0 -> bytes.Equal(a, b)'

# go documentation
# view full documentation for the strings package
go doc -all strings | less
# view documentation for the strings.Replace function
go doc strings.Replace
# show source code for strings.Replace
go doc -src strings.Replace | less

# offline http server that includes all go documentation, tutorial and books
go install golang.org/x/tools/cmd/godoc@latest
godoc -http=:6060 &             # run go documentation server (offline) :6060
open http://localhost:6060
pkill godoc

# dependency inspection
# list all packages the project depend on (direct & indirect)
go list all
# introspect Go packages and their interdependencies
go list -f '{{ join .Imports "\n" }}' # directly import packages the project depend on
# list all modules
go list -m all
# list outdated direct modules
go list -f '{{if and (not .Indirect) .Update}}{{.}}{{end}}' -u -m all
# use depth for different visualization
depth -explain regexp gtoken    # explain why specific package (regexp) is included into the project

# check the source code is compliant with the import packages license
golicense -verbose -license ../../.golicense.json .bin/gtoken

# build
# list supported architectures and OS for Go builder
go tool dist list
# build linux arm64 executable
GOOS=linux GOARCH=amd64 go build -o=.bin/$GOOS_$GOARCH/app .
# inspect linker flags
go tool link -help
# embed version info into build
export VERSION=$(git describe --tags --always --dirty)
export COMMIT=$(git rev-parse --short HEAD)
export BRANCH=$(git rev-parse --abbrev-ref HEAD)
export DATE=$(date +%FT%T%z)

go build -ldflags "-X main.Version=${VERSION} \
                   -X main.GitCommit=${COMMIT} \
                   -X main.GitBranch=${BRANCH} \
                   -X main.BuildDate=${DATE}" -o .bin/app

$ .bin/app --version    # to display above info

# static builds
# disable cgo, unless you need to interoperate with C libraries
# most likely - you do not need it
CGO_ENABLED=0
# Go linker flags
# -s: omit the symbol table and debug information
# -w: omit the DWARF symbol table
go build -ldflags='-s -w' -o=.bin/app

# build tags
# build (linux and arm64)
package app     # +build linux, arm64
# build/test only if '--tags=integration' is provided
package app
import "testing"    # +build integration

# test
go test                     # run tests
go test -cover              # run tests with code coverage
go test -race               # test with race condition

# tests/mock generation
go install github.com/cweill/gotests/gotests@latest
gotests                     # generate table driven tests
gotests -all -w main.go
mockery                     # generate mock for Go interfaces
mockery -all -inpkg

go test -v -cover .
richgo test -v -cover .     # same as above but with colors

# benchmark
go test -run=^$ -bench=. ./...      # run benchmark only, skipping tests
go test -bench=. | tee v1.txt       # output to file v1.txt and also terminal display
go test -bench=. | tee v2.txt       # output to file v2.txt and also terminal display
benchcmp v1.txt v2.txt              # compare benchmark results

# static analysis
# inspect vet tool
go tool vet help
go vet
# report unchecked errors
errcheck

# linters aggregator
golangci-lint run
golangci-lint linters               # list supported linters
golangci-lint run --enable-all      # run all linters

# profile (Ref: github.com/alexei-led/presentations)
# collect profile results: cpu, memory, block, mutex
go test -bench="^Benchmark(.*)$" -cpuprofile=/tmp/cpuprofile.out .
# inspect profile results
go tool pprof -http=:8080 /tmp/cpuprofile.out

# goimports install
Install goimports with the following command:
go install golang.org/x/tools/cmd/goimports@latest
And run it with:
goimports -w filename.go
Reference: https://pkg.go.dev/golang.org/x/tools/cmd/goimports

# linting program in golang
Install golint with the following command:
go install golang.org/x/lint/golint@latest
And run it with:
golint filename.go
golint ./...        // runs golint over your entire project

# language tools
go build        builds Go binaries using only information in the source files
go test         unit testing and microbenchmarks
go fmt          preprint the code
go get          retrieve and install remote packages
go vet          static analyzer looking for potential errors in code
go run          build and executing code (doesn't generate a binary executable)
go doc          display documentation or serving it via HTTP
go rename       rename variables, functions, and so on in a type-safe way
go generate     standard way to invoke code generators

Go is a statically typed programming language.

# Data types:
string
bool
int
int     int8    int16   int32   int64
uint    uint8   unit16  unit32  unint64     unintptr
byte - alias for uint8
rune - alias for int32
float32 (single precision)    float64 (double precision)
complex64   complex128

int - signed integer
uint - unsigned integer (contain positive numbers or zero)

bytes are an extremely common unit of measurement used on computers
(1 byte = 8 bits, 1024 bytes = 1 kilobyte, 1024 kilobytes = 1 megabyte, etc.)

there are also three machine dependent integer types: uint, int, and uintptr
they are machine dependent because their size depends on the type of architecture

* floating-point numbers are inexact.
  (Occasionally it is not possible to represent anumber.)
* like integers, floating-point numbers have a certain size (32 bit or 64 bit)
* using a larger-sized floating-point number increases its precision
* in addition to numbers, there are several other values that can be represented:
  "not a number" (NaN, for things like 0/0) and positive and negative infinity
* generally, we should stick with float64 when working with floating-point numbers

* a string is a sequence of characters with a definite length used to represent text
* go strings are made up of individual bytes, usually one for each character
* string literals can be created using double quotes "Mathematical Sciences" or
  backticks `Mathematical Sciences`
* the difference between these is that double-quoted strings cannot contain newlines
  and they allow special escape sequences.
* for example, \n gets replaced with a newline & \t gets replaced with a tab character

* a boolean value is a special 1-bit integer type used to represent true and false
* three logical operators are used with boolean values: && and, || or, ! not

Constants:      true  false  iota  nil
Types:          int     int8    int16   int32   int64
                uint    unit8   uint16  uint32  uint64  uintptr
                float32 float64 complex128  complex64
                bool  byte  rune  string  error

Functions:      make  len  cap  new  append  copy  close  delete  complex  real  imag
                panic  recover

Keywords: [Reference: https://go.dev/ref/spec]
The following keywords are reserved and may not be used as identifiers.
    break       default         func        interface       select
    case        defer           go          map             struct
    chan        else            goto        package         switch
    const       fallthrough     if          range           type
    continue    for             import      return          var


# package main - package declaration (every Go program must start with it. Packages are
Go's way of organizing and reusing code)

Go supports two different styles of comments: // comments in which all the text between
the // and the end of the line is part of the comment, and /*........ */ comments where
everything between the asterisks is part of the comment (may include multiple lines)

# format string
int: %d
float: %f, %.3f
string: %s
bool: %t

# go documentation example
go doc fmt Println

# fyne (https://developer.fyne.io/started/)
Debian: sudo apt-get install golang gcc libgl1-mesa-dev xorg-dev

# gonum
go install gonum.org/v1/gonum/...@latest

# A half-hour to learn Golang

var declares a variable of a given type:

var x int // Declare x of type int
x = 42    // Assign 42 to x

This can also be written as a single line:

var x int = 42

You can also specify the variable's type implicitly:

var x = 42  // Type int is inferred from 42

This can also be written using a short form:

x := 42

You can declare many variables at the same time:

var a, b, c int
a, b, c = 1, 2, 3
x, y := 40, 80

All declared variables are always initialized to the zero value. If you declare
a variable and use it right away, you can be sure itll have the zero value of
that type.

var x int
foo(x)  // Same as foo(0)

The underscore _ is a special identifier. It's used to indicate "no identifier"
and can be used to discard something, or mark it as "used":

// This does nothing because 42 is a constant
_ = 42

// This calls fetchThing but discards its result
_ = fetchThing()

You can import a package for side-effects only by using _ :

import _ "image/png"

A variable with the same name can be re-declared as long as it's in a different
block. That causes it tot shadow an existing variable:

x := 13
if true {
    x := x + 3
    // Using x after that line only refers to the second x,
    // the first x is no longer accessible in this scope.
}

Go does not have a concept of "tuples" like Rust, but it has struct types and
functions can return multiple result values.

Semicolons can be used to mark the end of a statement. But they are optional and
automatically inserted at the end of aline, so they're only needed if you're
placing multiple statements in one line:

var x = 3; var y = 5; var z = y + x

All Go code is formatted with gofmt, the standard Go code formatting tool. It
pretty prints Go code so each statement is on a single line, without semicolons:

var x = 3
var y = 5
var z = y + x

It aligns fields and makes Go code look consistent, no matter who wrote it:

header := component.Header{
    CurrentUser:        authenticatedUser,
    NotificationCount:  nc,
    ReturnURL:          returnURL,
}

Statements can span multiple lines:

notifications := initNotifications(
    http.DefaultServeMax,
    webdav.Dir(filepath.Join(storedir, "notifications")),
    gerritActivity,
    users,
    githubRouter,
)

func declares a function.

Here's a simple function:

func Greet() {
    fmt.Println("Hi there!")
}

Here's a function that returns a 32-bit signed integer:

func FairDiceRoll() int32 {
    return 4
}

A pair of brackets declare a block, which has its own scope:

func main() {
    x := "out"
    {
        // This is a different x.
        x := "in"
        fmt.Println(x)
    }
    fmt.Println(x)
}

Dots are typically used to access fields of a struct:

var x = struct{ a, b int }{10, 20}
x.a // This is 10.

dmitshur := fetchSomeStruct()
dmitshur.WebsiteURL // This is "https://dmitri.shuralyov.com".

Or call a method on a value:

w.Header().Set("Content-Type", "text/html; charset=utf-8")

Dots are also used to access exported identifiers from other Go packages that
are imported:

import "fmt"

func main() {
    fmt.Println("Println is a function in the fmt package")
}

Dots work for accessing struct fields regardless whether they're a value or a
pointer, which makes refactoring code result in a smaller diff.

Named types are declared with the type keyword.

type MyInt int

Struct types are defined with the struct keyword.

type Vec2 struct {
    X float64
    Y float64
}

They can be initialized using struct literals:

var v1 = Vec2{X: 1.0, Y: 3.0}
var v2 = Vec2{Y: 2.0, X: 4.0 /* The order does not matter, only the names do. */}

One value can be assigned to another:

var v3 = v2
v3.X = 14

You can declare methods on named structs that you defined:

type Number struct {
    Odd     bool
    Value   int32
}

// IsStrictlyPositive reports whether Number n is strictly positive.
func (n Number) IsStrictlyPositive() bool {
    return n.Value > 0
}

And use them like usual:

func main() {
    minusTwo := Number {
        Odd:    false,
        Value:  -2,
    }
    fmt.Println("positive?", minusTwo.IsStrictlyPositive())

    // Output:
    // positive? false
}

Values are mutable.

n := Number {
    Odd:    true,
    Value:  17,
}
n.Odd = false   // This modifies n.

Functions cannot be generic. They can accept parameters that have interface
types. All values implement the blank interface interface{}, so that's a way to
pass a parameter of arbitrary type.

func Println(arg interface{}) {
    // Do something with arg.
}

An interface can have 0 or more methods in its method set. When you have a value
of type interface, you can call any of the methods in the method set of said
interface.

type Stringer interface {
    String() string
}

func Priintln(s Stringer) {
    s.String() // s has a String method, you can call it.
}

Structs cannot be generic either.

Go has slices. They're a reference to multiple contiguous elements in an
underlying array.

v := []int{1, 2, 3, 4, 5}
v2 := v[2:4]
fmt.Printf("v2 = %v\n", v2)

// Output:
// v2 = [3, 4]

The v[2:4] syntax is a slice operation. It makes a new slice that references the
same underlying array as the v slice, but includes elements starting with index
2 and ending with index 4.

Functions that can fail typically return two result values, the last being of
type error:

u1, err := url.Parse("https://example.com/")
fmt.Println(u1.Host, err)
// Prints "example.com <nil>".

u2, err := url.Parse(":")
fmt.Println(u2, err)
// Prints "<nil> parse ":": missing protocol scheme".

If you want to panic in case of a non-nil error, you can use panic:

u, err := url.Parse(someURL)
if err != nil {
    panic(err)
}
fmt.Println(u.Host)

Or write any custom code to handle the non-nil error:

u, err := url.Parse(someURL)
if err != nil {
    // Custom behavior to handle the parsing error...
}
fmt.Println(u.Host)

Or you can return the error to the caller, so it can deal with the failure
appropriately:

u, err := url.Parse(someURL)
if err != nil {
    return nil, err
}
return u.Host, nil

Or annotate the error with relevant context:

u, err := url.Parse(someURL)
if err != nil {
    return nil, fmt.Errorf("failed to parse URL %q, so cannot determine its
    host: %v", someURL, err)
}
return u.Host, nil

The * operator can be used to dereference pointers, but it's done implicitly by
Go when accessing fields or calling methods:

type Point struct {
    X, Y float64
}

func main() {
    p := Point(1, 3)
    pp := &p
    fmt.Println(pp.X, pp.Y)
    // Output: 1 3
}

A function literal represents an anonymous function, It can be assigned to a
variable of function type.

var f func(string) = func(planet string) {
    fmt.Println("Hello", planet)
}

Function literals are closures; they may refer to variables defined in a
surrounding function. variables with function type can be passed around and
executed.

func main() {
    greeting := "Hello"
    greet := func(planet string) {
        fmt.Println(greeting, planet) // Variable greeting is captured.
    }

    forEachPlanet(greet)

    // Output:
    // Hello Earth
    // Hello Mars
    // Hello Jupiter
}

// forEachPlanet calls f for each planet.
func forEachPlanet(f func(string)) {
    f("Earth")
    f("Mars")
    f("Jupiter")
}

Anything that can be iterated over can be used in a for loop.

for i := 0; i < 3; i++ {
    fmt.Println("index", i)
}

// Output:
// index 0
// index 1
// index 2

There is also a for range loop.

s := []int{52, 49, 21}
for i, v := range s {
    fmt.Printf("index=%v value=%v\n", i, v)
}

// Output:
// index=0 value=52
// index=1 value=49
// index=2 value=21

# built-in operators
Operation                       Result              Description
--------------------------------------------------------------------------------------
0011 & 0101                     0001                Bitwise AND
0011 | 0101                     0111                Bitwise OR
0011 ^ 0101                     0110                Bitwise XOR
^0101                           1010                Bitwise NOT (same as 1111 ^ 0101)
0011 &^ 0101                    0010                Bitclear (AND NOT)
00110101 << 2                   11010100            Left shift
00110101 << 100                 00000000            No upper limit on shift count
00110101 >> 2                   00001101            Right shift

# package math/bits
Operation                       Result          Description
---------------------------------------------------------------------------------------
bits.UintSize                   32 or 64        Size of a uint in bits
bits.OnesCount8(00101110)       4               Number of one bits (population count)
bits.Len8(00101110)             6               Bits required to represent number
bits.Len8(00000000)             0
bits.LeadingZeros8(00101110)    2               Number of leading zero bits
bits.LeadingZeros8(00000000)    8
bits.TrailingZeros8(00101110)   1               Number of trailing zero bits
bits.TrailingZeros8(00000000)   8
bits.RotateLeft8(00101110, 3)   01110001        The value rotated left by 3 bits
bits.RotateLeft8(00101110, -3)  11000101        The value rotated right by 3 bits
bits.Reverse8(00101110)         01110100        Bits in reversed order
bits.ReverseBytes16(0x00ff)     0xff00          Bytes in reversed order

Reference: https://yourbasic.org/golang/bitwise-operator-cheat-sheet/
