Go (Golang) Cheat Sheet
Go reference with goroutines, channels, slices, maps, interfaces, and error patterns. Copy-ready code for Go developers.
Variables
| Syntax | Description | Example |
|---|---|---|
| Variable declaration with type | var name string = "Alice" | |
| Short variable declaration (inferred type) | count := 0 | |
| Constant declaration | const pi = 3.14159 | |
| Basic types | var age int = 30 | |
| Print with newline | fmt.Println("Hello", name) | |
| Formatted print | fmt.Printf("Name: %s, Age: %d\
", name, age) | |
| Format to string | s := fmt.Sprintf("%s is %d", name, age) | |
| Int to string / string to int | s := strconv.Itoa(42); n, _ := strconv.Atoi("42") | |
| Type conversion | f := float64(42); i := int(3.14) | |
| Multiple declarations | a, b, c := 1, "hello", true |
Strings
| Syntax | Description | Example |
|---|---|---|
| Byte length of string | len("hello") // 5 | |
| Check if string contains substring | strings.Contains("hello", "ell") // true | |
| Check start/end of string | strings.HasPrefix("hello", "he") // true | |
| Change case | strings.ToUpper("hello") // "HELLO" | |
| Remove whitespace | strings.TrimSpace(" hi ") // "hi" | |
| Split string into slice | strings.Split("a,b,c", ",") // ["a","b","c"] | |
| Join slice into string | strings.Join([]string{"a","b"}, ", ") // "a, b" | |
| Replace occurrences | strings.Replace("hello", "l", "r", -1) // "herro" | |
| Find position of substring | strings.Index("hello", "ll") // 2 | |
| Count occurrences | strings.Count("hello", "l") // 2 |
Slices
| Syntax | Description | Example |
|---|---|---|
| Fixed-size array | var nums [3]int = [3]int{1, 2, 3} | |
| Slice literal | s := []int{1, 2, 3} | |
| Create slice with make | s := make([]int, 0, 10) | |
| Append to slice | s = append(s, 4, 5, 6) | |
| Slice of slice | s[1:3] // elements at index 1, 2 | |
| Length / capacity of slice | fmt.Println(len(s), cap(s)) | |
| Copy slice elements | n := copy(dst, src) | |
| Sort a slice | sort.Ints(nums) | |
| Check if slice contains value (1.21+) | slices.Contains(nums, 42) |
Maps
| Syntax | Description | Example |
|---|---|---|
| Map literal | m := map[string]int{"a": 1, "b": 2} | |
| Create map with make | m := make(map[string]int) | |
| Set map entry | m["name"] = "Alice" | |
| Get with existence check | if val, ok := m["key"]; ok { ... } | |
| Delete map entry | delete(m, "name") | |
| Number of entries in map | fmt.Println(len(m)) | |
| Iterate over map | for key, val := range m { ... } |
Control Flow
| Syntax | Description | Example |
|---|---|---|
| Conditional | if x > 0 { fmt.Println("positive") } | |
| If with initialization | if err := doThing(); err != nil { ... } | |
| Switch (no break needed) | switch day { case "Mon": ... default: ... } | |
| Switch without value (if-else chain) | switch { case x>0: ... case x<0: ... } | |
| C-style for loop | for i := 0; i < 10; i++ { ... } | |
| While-style loop | for count < 10 { count++ } | |
| Infinite loop | for { if done { break } } | |
| Range over slice/map/string | for i, val := range nums { ... } | |
| Exit loop / skip iteration | if x == 5 { continue } | |
| Execute when function returns | defer file.Close() |
Functions
| Syntax | Description | Example |
|---|---|---|
| Function declaration | func add(a, b int) int { return a + b } | |
| Multiple return values | func divide(a, b float64) (float64, error) | |
| Anonymous function / closure | double := func(x int) int { return x * 2 } | |
| Variadic parameters | func sum(nums ...int) int { ... } | |
| Method on type (receiver) | func (u User) FullName() string { ... } | |
| Method with pointer receiver | func (u *User) SetName(n string) { u.Name = n } |
Types
| Syntax | Description | Example |
|---|---|---|
| Define a struct | type User struct { Name string; Age int } | |
| Struct literal | p := Point{X: 1.0, Y: 2.0} | |
| Define an interface | type Reader interface { Read(p []byte) (int, error) } | |
| Embed struct (composition) | type Admin struct { User; Level int } | |
| Type assertion | s := val.(string) | |
| Type switch | switch v := i.(type) { case int: ... } |
Concurrency
| Syntax | Description | Example |
|---|---|---|
| Launch goroutine | go processItem(item) | |
| Create channel | ch := make(chan int) | |
| Send to channel | ch <- 42 | |
| Receive from channel | result := <-ch | |
| Buffered channel | ch := make(chan int, 10) | |
| Wait on multiple channels | select { case v := <-ch1: ... case ch2 <- x: ... } | |
| Close a channel | close(ch) | |
| Wait for goroutines to finish | var wg sync.WaitGroup; wg.Add(1); go func() { defer wg.Done(); ... }() | |
| Mutual exclusion lock | var mu sync.Mutex; mu.Lock(); defer mu.Unlock() | |
| Cancellation and deadline propagation | ctx, cancel := context.WithTimeout(ctx, 5*time.Second) |
Errors
| Syntax | Description | Example |
|---|---|---|
| Error check pattern | if err != nil { return fmt.Errorf("failed: %w", err) } | |
| Create a simple error | return errors.New("not found") | |
| Formatted error | return fmt.Errorf("user %d not found", id) | |
| Check if error matches | if errors.Is(err, sql.ErrNoRows) { ... } | |
| Extract typed error | var pathErr *os.PathError; errors.As(err, &pathErr) | |
| Wrap error for unwrapping | fmt.Errorf("open: %w", err) |
Frequently asked questions
Why doesn't Go have generics?
Go added generics in version 1.18 (March 2022). You can now write func Map[T any, U any](s []T, f func(T) U) []U. Before 1.18, Go used interfaces and type assertions. Generics are still evolving - use them for data structures and utility functions.
How do goroutines differ from threads?
Goroutines are lightweight, managed by Go's runtime scheduler (not the OS). They start with ~2KB of stack, and millions can run concurrently. OS threads use ~1MB. The Go scheduler multiplexes goroutines onto a smaller number of OS threads.
Why does Go use if err != nil so much?
Go treats errors as values, not exceptions. This makes the error path explicit and visible. While verbose, it prevents hidden control flow from try/catch. The Go team considered error handling syntax proposals but prioritized simplicity.
What's the difference between arrays and slices?
Arrays have fixed size ([3]int), slices are dynamic ([]int). Slices are backed by arrays but can grow via append(). Almost always use slices - arrays are mostly for the underlying implementation.
Should I use pointers or values?
Use pointer receivers (*T) when methods modify the receiver or the struct is large. Use value receivers (T) for small, immutable types. For function parameters, pointers share data; values copy it. Be consistent within a type.
How do I structure a Go project?
Follow the standard layout: cmd/ for entry points, internal/ for private packages, pkg/ for public libraries. Keep packages small and focused. Use go mod for dependency management. Avoid the common mistake of over-structuring early.
Go from reference to real skills
Cheat sheets are great for quick lookups. Our in-depth courses take you from the fundamentals to professional-level mastery.
Browse all courses