Go Cheatsheet
Functions
Use this Go reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
Declaration Syntax
func name(param1 type1, param2 type2) returnType { // body }
func add(a, b int) int { // same-type params can share type return a + b } func greet(name string) string { return "Hello, " + name }
Multiple Return Values
Go functions can return any number of values. Use multiple returns instead of out-parameters.
func divide(a, b float64) (float64, error) { if b == 0 { return 0, errors.New("division by zero") } return a / b, nil } result, err := divide(10, 2) if err != nil { log.Fatal(err) }
Named Return Values
Named returns double as documentation and enable bare return.
func minMax(nums []int) (min, max int) { min, max = nums[0], nums[0] for _, v := range nums[1:] { if v < min { min = v } if v > max { max = v } } return // bare return; returns min and max }
Use named returns sparingly — they can reduce clarity in long functions.
Variadic Functions
...T accepts zero or more arguments of type T. Inside the function it behaves as []T.
func sum(nums ...int) int { total := 0 for _, n := range nums { total += n } return total } sum(1, 2, 3) sum() // spread a slice s := []int{1, 2, 3} sum(s...)
First-Class Functions
Functions are values — pass, return, and store them.
// assign to variable add := func(a, b int) int { return a + b } fmt.Println(add(3, 4)) // 7 // pass as argument func apply(op func(int, int) int, a, b int) int { return op(a, b) } apply(add, 2, 3) // return from function func multiplier(factor int) func(int) int { return func(n int) int { return n * factor } } double := multiplier(2) double(5) // 10
Closures
A closure captures variables from its enclosing scope.
func counter() func() int { count := 0 return func() int { count++ return count } } c := counter() c() // 1 c() // 2 c() // 3 // Each call to counter() creates its own independent count.
// Common gotcha: loop variable capture funcs := make([]func(), 5) for i := 0; i < 5; i++ { i := i // shadow to capture each value funcs[i] = func() { fmt.Println(i) } }
Anonymous Functions (immediately invoked)
result := func(x int) int { return x * x }(5) // 25
Recursive Functions
func factorial(n int) int { if n <= 1 { return 1 } return n * factorial(n-1) } // Mutual recursion — both must be declared before first call func isEven(n int) bool { return n == 0 || isOdd(n-1) } func isOdd(n int) bool { return n != 0 && isEven(n-1) }
Methods
A method is a function with a receiver. The receiver can be a value or pointer.
type Circle struct { Radius float64 } // Value receiver — receives a copy func (c Circle) Area() float64 { return math.Pi * c.Radius * c.Radius } // Pointer receiver — can mutate the original func (c *Circle) Scale(factor float64) { c.Radius *= factor } circ := Circle{Radius: 5} circ.Area() // 78.54... circ.Scale(2) // Radius becomes 10
Rule of thumb: use pointer receivers when the method mutates state, or when the type is large. Be consistent within a type — mix is allowed but confusing.
Pointer vs Value Receiver Summary
| Scenario | Use |
|---|---|
| Must modify receiver | Pointer *T |
| Large struct (avoid copy) | Pointer *T |
| Implements an interface requiring a pointer | Pointer *T |
| Small, immutable value type | Value T |
Function Types as Fields
type Handler func(http.ResponseWriter, *http.Request) type Middleware struct { Before func() After func() Handle func(string) string }
init Functions
init runs automatically after all variable initializations, before main. A package can have multiple init functions (even in the same file).
package main var db *sql.DB func init() { var err error db, err = sql.Open("postgres", os.Getenv("DSN")) if err != nil { log.Fatal(err) } } func main() { /* db is ready */ }
Defer Inside Functions
Deferred calls fire on return (including panic). See Control Flow for full defer details.
func writeFile(path, content string) error { f, err := os.Create(path) if err != nil { return err } defer f.Close() _, err = f.WriteString(content) return err }
Function Signature Patterns
// Error-returning constructor func NewServer(addr string) (*Server, error) { ... } // Options function pattern type Option func(*Server) func WithTimeout(d time.Duration) Option { return func(s *Server) { s.timeout = d } } // Context-first (idiomatic for cancellable operations) func Fetch(ctx context.Context, url string) ([]byte, error) { ... } // Functional options func NewServer(addr string, opts ...Option) *Server { s := &Server{addr: addr} for _, o := range opts { o(s) } return s }
Common Standard Library Functions
// math math.Abs(x) math.Sqrt(x) math.Pow(base, exp) math.Floor(x), math.Ceil(x), math.Round(x) math.Min(a, b), math.Max(a, b) math.Log(x), math.Log2(x), math.Log10(x) math.Inf(1), math.IsNaN(x), math.IsInf(x, 0) math.MaxInt, math.MinInt math.MaxFloat64 // math/rand (v2 in Go 1.22+) rand.IntN(100) // [0, 100) rand.Float64() // [0.0, 1.0) rand.Perm(n) // random permutation // sort sort.Ints(s) sort.Strings(s) sort.Float64s(s) sort.Slice(s, func(i, j int) bool { return s[i] < s[j] }) sort.SliceStable(...) sort.Search(n, f) // binary search sort.IntsAreSorted(s)