Go cheatsheet
See also: wiki/golang
Goroutines and channels
// buffer of 100 elements
ch := make(chan int, 100)
x, ok := <-ch // blocks if nothing to read
ch <- x // blocks until read (if unbuffered) or if buffer is full
// non-blocking read
select {
case x, ok := <-ch:
// ...
default:
// ...
}
// non-blocking write
select {
case ch <- x:
// ...
case <-context.Done():
return
default:
// ...
}
// wait for goroutines to finish
var wg sync.WaitGroup
wg.Add(1) // outside the goroutine!
go func() {
defer wg.Done()
...
}
wg.Wait()
Cancel goroutine
doneChannel := make(chan struct{})
go func() {
time.Sleep(1 * time.Minute)
close(doneChannel)
}()
go func() {
for {
// ...
select {
case <-doneChannel:
return
default:
continue
}
}
}()
Loops
for my_condition { ... }
for i := 0 ; i < n; i++ { ... }
for i, x := range xs { ... }
Type assertions and switches
s, ok := x.(string)
switch t := x.(type) {
case T1:
// `t` is value of type `T1`
case T2:
// `t` is value of type `T2`
default:
// ...
}
Package organization
- Commands go in
cmd/PACKAGE/main.go
; private packages go ininternal/
.
Be careful
- Reading from a closed channel is not an error. Always do
v, ok := <-ch
! break
in a select statement breaks out of theselect
statement itself, not any outer loop.- If spawning goroutines in a loop, don't do
for _, x := range xs { go func() { ... x ... }() }
– instead dogo func(x T) { ... }(x)
to ensure the correct value ofx
is captured. - If passing an anonymous function to
defer
, make sure to call it:defer func() { ... }()
- Indexing a string gives you a byte, not a Unicode character. Use the
utf8
package to work with UTF-8 strings.
Commands
go mod init github.com/iafisher/PROJECT
go get github.com/OWNER/REPO
go get github.com/OWNER/REPO@none
(uninstall)go run cmd/server/main.go
go build -o server cmd/server/main.go
env GOOS=linux GOARCH=amd64 go build ...
go test ./...
go test -test.run FUNC
dlv debug PKG
dlv test PKG -- -test.run FUNC