Table of Content
- Tutorials
- Commands
- go mod init - Initialize a new module
- go mod tidy - Add missing dependencies or remove unused ones
- go mod edit - Edit and format go.mod file
- go mod vendor - Copy dependencies with mod vendor
- go run - Run the app
- go test - Run tests
- go build - Build
- go install - Install
- go fmt - Format files
- go fix - Update packages to use new APIs
- go vet - Get mistakes with go vet
- go clean - Remove files and clean cache
- go list - List packages and modules
- go doc - Generate documentation
- Debugging
- Linting & fixing common problems
- The language
- Random
- Testing and linting in pipeline
- Other resources to check
Follow along for go.dev tutorials:
- Getting started with go
- Create Go modules series
- RESTful API with Go and Gin. Tutorial's README here.
Follow along for freeCodeCamp tutorials. Tutorial's README here.
go mod init [module-path] go mod init /
- creates a new
go.mod
file in current directory - the file must not exist already
go mod tidy [-e] [-v] [-go=version] [-compat=version]
[-e]
- continue with errors[-v]
- info for removed modules[-go]
- sets version, enable or disable module graph pruning and module loading based on version (changes from go 1.17)[-compat]
- set the version to be checked for compatibility
go mod edit [editing flags] [-fmt|-print|-json] [go.mod]
Example:
go mod edit -replace random-prefix/greetings=../greeting
[editing flags]
-module
,-go=version
,-require=path@version
/-droprequire=path
,-exclude=path@version
/-dropexclude=path@version
,-replace=old[@v]=new[@v]
,-dropreplace=old[@v]
,-retract=version
/-dropretract=version
- can have multiple editing flags
[-fmt]
- format
- implicit as part of other
go mod edit
commands
[-print]
- print as text instead of writing to disk
[-json]
- returns a json instead of writing to disk
go mod vendor [-e] [-v] [-o outdir]
[-v]
- print the names of vendored modules and packages to standard error
[-e]
- causes vendor to attempt to proceed despite errors encountered while loading packages
[-o]
- causes vendor to create the vendor directory at the given path instead of "vendor"
go run [build flags] [-exec xprog] package [arguments...]
- compile and run the
main
go package - single package:
go run .
- with path:
go run my/cmd
go test [build/test flags] [packages] [build/test flags & test binary flags]
- run tests for files matching the filename pattern
*_test.go
and functions namedTestXxx
(afterTest
there needs to be an upper case - exported name) - these files can contain tests, benchmark or example functions
More info:
go help testfunc
go build [-o output] [build flags] [packages]
- compiles the packages, along with their dependencies, doesn't install the results
- ignores files that end in
_test.go
go install [build flags] [packages]
- compiles and installs the packages
- compile and install
go fmt [-n] [-x] [packages]
[-n]
- prints commands that would be executed
[-x]
- prints commands as they are executed
[-mod]
- sets which module download mode to use:
readonly
orvendor
- sets which module download mode to use:
go fix [-fix list] [packages]
[-fix]
- sets a comma-separated list of fixes to run. The default is all known fixes.
go vet [-n] [-x] [-vettool prog] [build flags] [vet flags] [packages]
[-n]
- prints commands that would be executed
[-x]
- prints commands as they are executed
[-vettool=prog]
- selects a different analysis tool with alternative or additional checks
Example:
- the 'shadow' analyzer can be built and run:
go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow go vet -vettool=$(which shadow)
go clean [clean flags] [build flags] [packages]
Example:
go clean -i
- remove the corresponding installed archive or binary added by
go install
go list [-f format] [-json] [-m] [list flags] [build flags] [packages]
Example:
- the installation path after compiling
caller
into an executable
go list -f '{{.Target}}'
- an array will all available
.go
files under current path
go list -f '{{.GoFiles}}'
- print the package data in JSON format
go list -json
go doc [doc flags] [package|[package.]symbol[.methodOrField]]
Example:
- documentation for formatting files
go doc cmd/gofmt
- show all documentation for the package
go doc -all
The standard debugger for Go applications is Delve - commands
go install github.com/go-delve/delve/cmd/dlv@latest
Check it was correctly installed with dlv version
or with a path ~/go/bin/dlv
.
Using Delve:
dlv debug main.go break bp1 main.main:3 condition bp1 i == 2 continue next step stepout restart exit
print set = locals whatis
- applies the rules based on Effective Go and a collection of comments from code reviews.
- can't be configured
- provides support for controlling which rules are applied
go install github.com/mgechev/revive@latest revive
- you can disable or enable a rule in code:
// revive:disable:exported
// revive:enable:exported
- the configuration file for this linter is
revive.toml
- run the linter with configuration file
revive -config revive.toml
go vet go vet main.go go vet -json main.go
go vet -assign=false go vet -assign
- a function named starting with a capital letter can be called by a function not in the same package
- if calling a function from a different package with a lower letter you get an error: cannot refer to unexported name xxxxx
- used for declaring and initializing a variable
message := fmt.Sprintf("Hi, %v. Welcome!", name)
// Same as
var message string
message = fmt.Sprintf("Hi, %v. Welcome!", name)
// Definition
func Hello(name string) (string, error) {
if name == "" {
return "", errors.New("empty name")
}
message := fmt.Sprintf("Hi, %v. Welcome!", name)
return message, nil
}
// Calling the function
message, err := greetings.Hello("")
- named results are initialized
func ReadFull(r Reader, buf []byte) (n int, err error) {
for len(buf) > 0 && err == nil {
var nr int
nr, err = r.Read(buf)
n += nr
buf = buf[nr:]
}
return
}
- the array's size is fixed
- the length is part of its type (
[4]int
is distinct and incompatible with[3]int
) - can be indexed -
s[n]
will return the nth element, starting from 0
var a [4]int
a[0] = 1
i := a[0] // i = 1
- arrays don't need to be initialized explicitly
- the arrays are values, the variable is not a pointer to the first element but represents the entire array
- assigning an array value makes a copy of the content
b := [2]string{"Penn", "Teller"}
// or
b := [...]string{"Penn", "Teller"}
letters := []string{"a", "b", "c"}
// or
var s[]byte
// Using func make([]T, len, cap) []T
s = make([]byte, 5, 5) // s = []byte{0, 0, 0, 0, 0}
// or
s = make([]byte, 5)
- can form a slice from "slicing" an existing slice or array
b := []byte{'g', 'o', 'l', 'a', 'n', 'g'}
// b[1:4] == []byte{'o', 'l', 'a'}
// b[:2] = []byte{'g', 'o'}
// b[2:] = []byte{'l', 'a', 'n', 'g'}
// b[:] = b
// Create slíce from array
golang := [6]byte{'g', 'o', 'l', 'a', 'n', 'g'}
s := golang[:]
b[1:4]
shares the same storage asb
- doesn't copy the slice's data, but it creates a new slice value that points to the original array
d := [byte]{'r', 'o', 'a', 'd'}
e := d[2:]
e[1] = 'm'
// d = [byte]{'r', 'o', 'a', 'm'}
// e = [byte]{'a', 'm'}
-
getting the length (the number of elements referred to by the slice) and the capacity (the number of elements in the underlying array) with
len(s)
andcap(s)
-
can't grow a slice beyond its capacity and can't index outside the bounds - these cause runtime panic
-
slices can't be re-sliced below 0
-
copy data from a source slice to a destination, returning the number of elements copied
func copy (dest, src []T) int
- append the elements
x
to the end of the slices
; it will take care of increasing the size of the slice if needed
func copy (s []T, x ...T) []T
Example:
a := make([]int, 1) // a = []int{0}
a = appent(a, 1, 2, 3) // a = []int{0, 1, 2, 3}
- append one slice to another with
...
to expand the second slice
a := []int{1, 2, 3}
b := []int{4, 5, 6}
a = append(a, b...) // a = append(a, b[0], b[1], b[2])
- the
init
functions are automatically executed at program setup - used for initializations that can't be done by declarations, verifications of program state
- first the imported packages are initialized, then the global variables are initialized, then the
init
function is called - each file can have multiple init
functions
- documentation and article link
- include the contents of arbitrary files and directories with
//go:embed FILENAME(S)
followed by astring
or[]byte
variable for one file orembed.FS
for a group of files - patterns like
files/*.html
will also work (but not**/*.html
recursive globbing)
package main
import (
_ "embed"
"fmt"
"strings"
)
var (
Version string = strings.TrimSpace(version)
//go:embed version.txt
version string
)
func main() {
fmt.Printf("Version %q\n", Version)
}
Include version information conditionally based on whether a build tag is passed to the go tools:
// version_dev.go file:
//go:build !prod
// +build !prod
package main
var version string = "dev"
Run:
$ go run .
Version "dev"
// version_prod.go file:
//go:build prod
// +build prod
package main
import (
_ "embed"
)
//go:embed version.txt
var version string
Run:
$ go run -tags prod .
Version "0.0.1"
- need to import the
embed
package in any file that uses an embed directive - can only use
//go:embed
for variables at the package level, not within functions or methods - when you include a directory, it won’t include files that start with
.
or_
, but if you use a wildcard, likedir/*
, it will include all files that match, even if they start with.
or_
- use
//go:embed dir
or//go:embed dir/*.ext
for security reasons (otherwise you will accidentally include Mac OS's.DS_Store
)
- use
- for security reasons, Go also won’t follow symbolic links or go up a directory when embedding
- article link
- automate the running of tools to generate source code before compilation
Can use -ldflags
to override string values:
package main
import (
"fmt"
)
var VersionString = "unset"
func main() {
fmt.Println("Version:", VersionString)
}
Run:
$ go run main.go
Version: unset
$ go run -ldflags '-X main.VersionString=1.0' main.go
Version: 1.0
# Can use git commit hash:
$ go run -ldflags "-X main.VersionString=`git rev-parse HEAD`" main.go
Version: db5c7db9fe3b632407e9f0da5f7982180c438929
# Need single quote if there is a space
$ go run -ldflags "-X 'main.VersionString=1.0 (beta)'" main.go
Version: 1.0 (beta)
# Ca use the standard Unix date command
$ go run -ldflags "-X 'main.VersionString=`date`'" main.go
Version: Sun Nov 27 16:42:10 EST 2016
package project
//go:generate echo Hello, Go Generate!
func Add(x, y int) int {
return x + y
}
Run:
$ go generate
Hello, Go Generate!
Can be used with tools like stringer, jsonenums and schematyper.
- documentation, go help buildconstraint
- condition under which a file should be included in the package
Project here for GitHub Actions use.
-
Udemy - Building web applications with go - intermediate level
-
go.dev - Getting started with multi-module workspaces
- needs go 1.18 or later
-
go.dev - Getting started with generics
- needs go 1.18 or later
-
go.dev - Getting started with fuzzing
- needs go 1.18 or later
Exercises and challenges: