Go Cheat Sheet

A comprehensive Go (Golang) reference guide with syntax, examples, and usage instructions. Find the Go concepts, functions, goroutines, channels, and commands you need using the search bar or browse by category.

📚 Practice what you've learned with our Go Flashcards

25 concepts found
Filter by category:

Variables

Basic Syntax

Declare and initialize variables in Go

Syntax:

var name type = value
name := value  // short declaration

Examples:

var name string = "John"
Explicit type declaration
age := 25
Short variable declaration
var x, y int = 10, 20
Multiple variable declaration
var (
    name = "Alice"
    age  = 30
)
Variable block declaration

Notes:

Go is statically typed. Use := for new variables, = for existing ones

Constants

Basic Syntax

Declare constants in Go

Syntax:

const NAME = value
const NAME type = value

Examples:

const Pi = 3.14159
Simple constant
const MaxUsers int = 100
Typed constant
const (
    Red   = "red"
    Green = "green"
    Blue  = "blue"
)
Constant block
const (
    A = iota  // 0
    B         // 1
    C         // 2
)
Using iota for enumeration

Notes:

Constants are computed at compile time and cannot be changed

Functions

Basic Syntax

Define and call functions in Go

Syntax:

func name(param type) returnType {
    return value
}

Examples:

func greet(name string) string {
    return "Hello, " + name
}
Simple function with return
func add(a, b int) int {
    return a + b
}
Function with multiple parameters
func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("division by zero")
    }
    return a / b, nil
}
Function with multiple return values
func sum(nums ...int) int {
    total := 0
    for _, num := range nums {
        total += num
    }
    return total
}
Variadic function

Notes:

Functions are first-class citizens and can return multiple values

Structs

Basic Syntax

Define custom types using structs

Syntax:

type Name struct {
    field1 type1
    field2 type2
}

Examples:

type Person struct {
    Name string
    Age  int
}
Basic struct definition
p := Person{Name: "Alice", Age: 30}
Struct initialization
type User struct {
    ID       int    `json:"id"`
    Username string `json:"username"`
    Email    string `json:"email"`
}
Struct with JSON tags
func (p Person) Greet() string {
    return "Hello, I'm " + p.Name
}
Method on struct

Notes:

Structs are value types and support methods and tags for serialization

Packages

Basic Syntax

Organize code using packages

Syntax:

package name
import "package/path"

Examples:

package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}
Main package with import
import (
    "fmt"
    "os"
    "time"
)
Multiple imports
import (
    f "fmt"
    _ "github.com/lib/pq"
)
Import alias and blank import
package utils

// Exported function (capitalized)
func FormatName(s string) string {
    return strings.Title(s)
}

// unexported function
func helper() {}
Package with exported/unexported functions

Notes:

Capitalized names are exported (public), lowercase names are private to package

Arrays & Slices

Data Types

Work with arrays and slices in Go

Syntax:

var arr [size]type
var slice []type
slice := make([]type, len, cap)

Examples:

var arr [3]int = [3]int{1, 2, 3}
Array declaration and initialization
slice := []string{"apple", "banana", "cherry"}
Slice literal
nums := make([]int, 5, 10)
fmt.Println(len(nums), cap(nums))  // 5, 10
Creating slice with make
slice = append(slice, "date")
slice = append(slice, "elderberry", "fig")
Appending to slice
subSlice := slice[1:3]  // elements 1 and 2
Slice operations

Notes:

Arrays have fixed size, slices are dynamic. Use slices for most cases

Maps

Data Types

Use maps for key-value pairs

Syntax:

var m map[keyType]valueType
m := make(map[keyType]valueType)

Examples:

ages := map[string]int{
    "Alice": 30,
    "Bob":   25,
}
Map literal
m := make(map[string]int)
m["key"] = 42
Creating and setting map values
value, ok := m["key"]
if ok {
    fmt.Println("Found:", value)
}
Checking if key exists
delete(m, "key")  // Remove key-value pair
Deleting from map
for key, value := range ages {
    fmt.Printf("%s: %d\n", key, value)
}
Iterating over map

Notes:

Maps are reference types and must be initialized before use

Interfaces

Data Types

Define interfaces for polymorphism

Syntax:

type InterfaceName interface {
    Method1() returnType
    Method2(param type) returnType
}

Examples:

type Writer interface {
    Write([]byte) (int, error)
}
Simple interface definition
type Shape interface {
    Area() float64
    Perimeter() float64
}
Interface with multiple methods
func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

// Rectangle implements Shape interface
Implementing interface implicitly
var s Shape = Rectangle{Width: 10, Height: 5}
area := s.Area()  // Polymorphism
Using interface for polymorphism
func describe(i interface{}) {
    fmt.Printf("Type: %T, Value: %v\n", i, i)
}
Empty interface (any type)

Notes:

Interfaces are implemented implicitly. Empty interface{} accepts any type

Pointers

Data Types

Work with memory addresses using pointers

Syntax:

var p *type
p = &variable
value := *p

Examples:

var p *int
x := 42
p = &x
fmt.Println(*p)  // 42
Basic pointer usage
func increment(x *int) {
    *x++
}

num := 5
increment(&num)
fmt.Println(num)  // 6
Passing pointer to function
p := new(int)  // Allocates memory, returns pointer
*p = 100
Using new() to allocate memory
type Person struct {
    Name string
}
p := &Person{Name: "Alice"}
Pointer to struct

Notes:

Go has pointers but no pointer arithmetic. Use & to get address, * to dereference

Goroutines

Concurrency

Run functions concurrently using goroutines

Syntax:

go function()
go func() { }()

Examples:

go fmt.Println("Hello from goroutine")
Simple goroutine
go func() {
    fmt.Println("Anonymous goroutine")
}()
Anonymous function goroutine
for i := 0; i < 3; i++ {
    go func(id int) {
        fmt.Printf("Worker %d\n", id)
    }(i)
}
Multiple goroutines with parameters
var wg sync.WaitGroup
wg.Add(1)
go func() {
    defer wg.Done()
    fmt.Println("Work done")
}()
wg.Wait()
Using WaitGroup to wait for goroutines

Notes:

Goroutines are lightweight threads managed by Go runtime. Always ensure proper synchronization

Channels

Concurrency

Communicate between goroutines using channels

Syntax:

ch := make(chan type)
ch := make(chan type, bufferSize)  // buffered

Examples:

ch := make(chan string)
go func() {
    ch <- "Hello"
}()
msg := <-ch
fmt.Println(msg)
Basic channel communication
ch := make(chan int, 2)  // Buffered channel
ch <- 1
ch <- 2
fmt.Println(<-ch, <-ch)
Buffered channel
ch := make(chan int)
close(ch)
val, ok := <-ch
fmt.Println(val, ok)  // 0, false
Closing channels and checking status
for val := range ch {
    fmt.Println(val)
}
Ranging over channel
ch := make(chan<- int)  // Send-only
ch2 := make(<-chan int)  // Receive-only
Directional channels

Notes:

Channels enable safe communication between goroutines. Use buffered channels to avoid blocking

Select Statement

Concurrency

Handle multiple channel operations

Syntax:

select {
case <-ch1:
    // handle
case ch2 <- value:
    // handle
default:
    // default case
}

Examples:

select {
case msg := <-ch1:
    fmt.Println("Received:", msg)
case <-time.After(1 * time.Second):
    fmt.Println("Timeout")
}
Select with timeout
select {
case ch1 <- value:
    fmt.Println("Sent to ch1")
case ch2 <- value:
    fmt.Println("Sent to ch2")
default:
    fmt.Println("No channels ready")
}
Non-blocking select with default
for {
    select {
    case msg := <-ch:
        process(msg)
    case <-quit:
        return
    }
}
Select in infinite loop

Notes:

Select lets goroutines wait on multiple channel operations. Default case makes it non-blocking

Mutex

Concurrency

Synchronize access to shared resources

Syntax:

var mu sync.Mutex
mu.Lock()
defer mu.Unlock()

Examples:

type Counter struct {
    mu    sync.Mutex
    value int
}

func (c *Counter) Increment() {
    c.mu.Lock()
    defer c.mu.Unlock()
    c.value++
}
Using mutex for thread-safe operations
var mu sync.RWMutex

func read() {
    mu.RLock()
    defer mu.RUnlock()
    // Read operation
}
Read-write mutex for concurrent reads
var once sync.Once

func initialize() {
    once.Do(func() {
        fmt.Println("Initialized once")
    })
}
Using sync.Once for one-time initialization

Notes:

Always use defer to unlock mutex. RWMutex allows multiple readers or one writer

Error Handling

Error Handling

Handle errors in Go using the error interface

Syntax:

if err != nil {
    // handle error
}

Examples:

result, err := someFunction()
if err != nil {
    log.Fatal(err)
}
Basic error checking
import "errors"

func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("division by zero")
    }
    return a / b, nil
}
Creating custom errors
import "fmt"

type ValidationError struct {
    Field string
    Value string
}

func (e *ValidationError) Error() string {
    return fmt.Sprintf("validation failed for %s: %s", e.Field, e.Value)
}
Custom error type
err := someFunction()
if err != nil {
    return fmt.Errorf("failed to process: %w", err)
}
Error wrapping with fmt.Errorf

Notes:

Errors are values, not exceptions. Always check and handle errors explicitly

Panic & Recover

Error Handling

Handle exceptional conditions with panic and recover

Syntax:

panic("message")
defer func() {
    if r := recover(); r != nil {
        // handle panic
    }
}()

Examples:

func safeDivide(a, b int) (result int) {
    defer func() {
        if r := recover(); r != nil {
            result = 0
        }
    }()
    return a / b
}
Using recover to handle panic
if x < 0 {
    panic("x cannot be negative")
}
Using panic for unrecoverable errors
func cleanup() {
    if r := recover(); r != nil {
        fmt.Printf("Recovered from panic: %v\n", r)
        // Perform cleanup
    }
}

func main() {
    defer cleanup()
    panic("Something went wrong")
}
Panic with cleanup using defer

Notes:

Use panic for programmer errors, not for normal error handling. Recover only works inside deferred functions

HTTP Server

HTTP & Web

Create HTTP servers using net/http package

Syntax:

http.HandleFunc("/path", handler)
http.ListenAndServe(":port", nil)

Examples:

import "net/http"

func hello(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, World!")
}

func main() {
    http.HandleFunc("/", hello)
    http.ListenAndServe(":8080", nil)
}
Basic HTTP server
func apiHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(map[string]string{"message": "Hello API"})
}
JSON API endpoint
mux := http.NewServeMux()
mux.HandleFunc("/users", usersHandler)
mux.HandleFunc("/posts", postsHandler)
http.ListenAndServe(":8080", mux)
Using custom mux for routing
server := &http.Server{
    Addr:         ":8080",
    Handler:      mux,
    ReadTimeout:  10 * time.Second,
    WriteTimeout: 10 * time.Second,
}
server.ListenAndServe()
HTTP server with timeouts

Notes:

net/http package provides a complete HTTP server implementation

HTTP Client

HTTP & Web

Make HTTP requests using net/http package

Syntax:

resp, err := http.Get(url)
resp, err := http.Post(url, contentType, body)

Examples:

resp, err := http.Get("https://api.example.com/data")
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
Simple GET request
data := strings.NewReader(`{"name": "John"}`)
resp, err := http.Post("https://api.example.com/users", "application/json", data)
POST request with JSON
client := &http.Client{
    Timeout: 30 * time.Second,
}
resp, err := client.Get(url)
HTTP client with timeout
req, _ := http.NewRequest("PUT", url, body)
req.Header.Set("Authorization", "Bearer token")
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
Custom request with headers

Notes:

Always close response body and handle timeouts for production code

JSON Handling

HTTP & Web

Work with JSON data using encoding/json

Syntax:

json.Marshal(v)
json.Unmarshal(data, &v)

Examples:

type User struct {
    ID   int    `json:"id"`
    Name string `json:"name"`
}

user := User{ID: 1, Name: "Alice"}
data, _ := json.Marshal(user)
Marshal struct to JSON
jsonStr := `{"id": 1, "name": "Bob"}`
var user User
err := json.Unmarshal([]byte(jsonStr), &user)
Unmarshal JSON to struct
encoder := json.NewEncoder(w)  // w is io.Writer
encoder.Encode(user)
Stream encoding to writer
decoder := json.NewDecoder(r)  // r is io.Reader
var user User
err := decoder.Decode(&user)
Stream decoding from reader

Notes:

Use struct tags to control JSON field names. Marshal/Unmarshal for []byte, Encode/Decode for streams

Unit Tests

Testing

Write unit tests using the testing package

Syntax:

func TestName(t *testing.T) {
    // test code
}

Examples:

func TestAdd(t *testing.T) {
    result := Add(2, 3)
    if result != 5 {
        t.Errorf("Add(2, 3) = %d; want 5", result)
    }
}
Basic unit test
func TestDivide(t *testing.T) {
    _, err := Divide(10, 0)
    if err == nil {
        t.Error("Expected error for division by zero")
    }
}
Testing error conditions
func TestMultiple(t *testing.T) {
    tests := []struct {
        a, b, want int
    }{
        {2, 3, 6},
        {4, 5, 20},
        {0, 10, 0},
    }
    
    for _, tt := range tests {
        got := Multiply(tt.a, tt.b)
        if got != tt.want {
            t.Errorf("Multiply(%d, %d) = %d; want %d", tt.a, tt.b, got, tt.want)
        }
    }
}
Table-driven tests

Notes:

Run tests with 'go test'. Test files must end with _test.go

Benchmarks

Testing

Write performance benchmarks

Syntax:

func BenchmarkName(b *testing.B) {
    for i := 0; i < b.N; i++ {
        // code to benchmark
    }
}

Examples:

func BenchmarkFibonacci(b *testing.B) {
    for i := 0; i < b.N; i++ {
        Fibonacci(20)
    }
}
Basic benchmark
func BenchmarkStringBuilder(b *testing.B) {
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        var sb strings.Builder
        for j := 0; j < 100; j++ {
            sb.WriteString("hello")
        }
        _ = sb.String()
    }
}
Benchmark with timer reset
func BenchmarkSort(b *testing.B) {
    data := make([]int, 1000)
    b.ResetTimer()
    
    for i := 0; i < b.N; i++ {
        b.StopTimer()
        copy(data, originalData)
        b.StartTimer()
        
        sort.Ints(data)
    }
}
Benchmark with setup excluded from timing

Notes:

Run benchmarks with 'go test -bench=.'. Use b.ResetTimer() to exclude setup time

Go Modules

Package Management

Manage dependencies using Go modules

Syntax:

go mod init module-name
go mod tidy
go get package@version

Examples:

go mod init github.com/user/project
Initialize new module
go get github.com/gin-gonic/gin
Add dependency
go get github.com/gin-gonic/gin@v1.9.1
Add specific version
go mod tidy
Clean up dependencies
go mod download
Download dependencies
go list -m all
List all dependencies

Notes:

Go modules are the official dependency management system since Go 1.11

Go CLI Commands

Package Management

Common Go command line operations

Syntax:

go command [arguments]

Examples:

go run main.go
Run Go program directly
go build -o myapp main.go
Build executable
go install github.com/user/tool@latest
Install Go program
go test ./...
Run all tests recursively
go test -v -cover
Run tests with verbose output and coverage
go fmt ./...
Format all Go files
go vet ./...
Static analysis of code

Notes:

Go CLI provides comprehensive tooling for development, testing, and deployment

Gin Framework

Popular Libraries

HTTP web framework for building APIs

Syntax:

import "github.com/gin-gonic/gin"

Examples:

r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
    c.JSON(200, gin.H{"message": "pong"})
})
r.Run(":8080")
Basic Gin server
r.POST("/users", func(c *gin.Context) {
    var user User
    if err := c.ShouldBindJSON(&user); err != nil {
        c.JSON(400, gin.H{"error": err.Error()})
        return
    }
    c.JSON(201, user)
})
POST endpoint with JSON binding
r.GET("/users/:id", func(c *gin.Context) {
    id := c.Param("id")
    c.JSON(200, gin.H{"user_id": id})
})
URL parameters
r.Use(gin.Logger())
r.Use(gin.Recovery())
r.Use(corsMiddleware())
Middleware usage

Notes:

Gin is a high-performance HTTP framework with minimal memory footprint

Echo Framework

Popular Libraries

Minimalist web framework for Go

Syntax:

import "github.com/labstack/echo/v4"

Examples:

e := echo.New()
e.GET("/", func(c echo.Context) error {
    return c.String(http.StatusOK, "Hello, World!")
})
e.Logger.Fatal(e.Start(":8080"))
Basic Echo server
e.POST("/users", func(c echo.Context) error {
    u := new(User)
    if err := c.Bind(u); err != nil {
        return err
    }
    return c.JSON(http.StatusCreated, u)
})
POST with data binding
e.GET("/users/:id", func(c echo.Context) error {
    id := c.Param("id")
    return c.JSON(http.StatusOK, map[string]string{"id": id})
})
URL parameters with Echo
e.Use(middleware.Logger())
e.Use(middleware.Recover())
e.Use(middleware.CORS())
Echo middleware

Notes:

Echo is optimized for high performance and extensibility with rich middleware ecosystem

GORM ORM

Popular Libraries

Object Relational Mapping library for Go

Syntax:

import "gorm.io/gorm"

Examples:

import "gorm.io/driver/sqlite"

db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
db.AutoMigrate(&User{})
Database connection and migration
user := User{Name: "Alice", Email: "alice@example.com"}
result := db.Create(&user)
Create record
var user User
db.First(&user, 1)  // find by primary key
db.First(&user, "name = ?", "Alice")  // find by condition
Query records
db.Model(&user).Update("name", "Bob")
db.Model(&user).Updates(User{Name: "Bob", Age: 30})
Update records
var users []User
db.Where("age > ?", 18).Find(&users)
db.Order("age desc").Limit(10).Find(&users)
Advanced queries

Notes:

GORM provides a full-featured ORM with auto-migration, associations, and hooks

Go Programming Tips

Best Practices

  • • Follow effective Go guidelines - use gofmt, goimports, and go vet
  • • Handle errors explicitly - avoid ignoring them with blank identifier
  • • Use goroutines for concurrency, not for parallelism by default
  • • Prefer composition over inheritance - use interfaces and embedding
  • • Keep interfaces small - prefer many small interfaces over few large ones

Performance Tips

  • • Use slices instead of arrays for better performance and flexibility
  • • Pre-allocate slices and maps when size is known using make()
  • • Use string builder for concatenating multiple strings efficiently
  • • Avoid creating goroutines in tight loops - use worker pools instead
  • • Use buffered channels to reduce goroutine blocking

Go Concurrency Patterns

Channel Patterns

  • • Pipeline: Chain goroutines with channels for data processing
  • • Fan-out/Fan-in: Distribute work across multiple goroutines
  • • Worker Pool: Fixed number of workers processing from a queue
  • • Select with Timeout: Prevent goroutines from blocking indefinitely

Synchronization

  • • Mutex: Protect shared resources from concurrent access
  • • RWMutex: Allow multiple readers or one writer
  • • WaitGroup: Wait for collection of goroutines to finish
  • • Once: Execute initialization code exactly once

Learning Go

Getting Started

  • • Install Go from golang.org
  • • Set up GOPATH and GOROOT (or use Go modules)
  • • Learn basic syntax and data types
  • • Practice with Go Playground (play.golang.org)

Intermediate Topics

  • • Interfaces and method sets
  • • Goroutines and channel communication
  • • Error handling patterns
  • • Package design and organization

Advanced Topics

  • • Reflection and runtime inspection
  • • Build constraints and cross-compilation
  • • Performance profiling with pprof
  • • CGO for C integration

Quick Reference Guide

Go Data Types Reference

Basic Types

TypeExampleZero ValueDescription
int420Platform-dependent integer
string"hello"""UTF-8 string
booltruefalseBoolean values
[]int[1, 2, 3]nilDynamic array
map[string]int{"a": 1}nilHash table
chan intmake(chan int)nilCommunication channel
*int&xnilPointer to int
interface{}any valuenilEmpty interface (any type)

Common Operations

Type Checking:

value, ok := x.(Type) - Type assertion

reflect.TypeOf(x) - Get type at runtime

Memory Allocation:

new(Type) - Allocate and return pointer

make([]Type, len, cap) - Create slices, maps, channels

Length and Capacity:

len(slice) - Get length of slice/map/channel

cap(slice) - Get capacity of slice/channel

Common Go Packages

Standard Library

  • • fmt - Formatted I/O
  • • net/http - HTTP client/server
  • • encoding/json - JSON handling
  • • time - Time utilities
  • • os - Operating system interface

Concurrency

  • • sync - Synchronization primitives
  • • context - Request-scoped values
  • • sync/atomic - Atomic operations
  • • runtime - Go runtime functions

Testing & Debugging

  • • testing - Testing framework
  • • log - Logging utilities
  • • errors - Error handling
  • • reflect - Runtime reflection

Go CLI Commands Reference

Development

go run main.go
go build -o app
go install
go fmt ./...
go vet ./...

Testing

go test ./...
go test -v -cover
go test -bench=.
go test -race
go test -short

Modules

go mod init
go mod tidy
go get package
go mod download
go list -m all