123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665 |
- # 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/
|