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
Variables
Basic SyntaxDeclare and initialize variables in Go
Syntax:
var name type = value
name := value // short declaration
Examples:
var name string = "John"
Explicit type declarationage := 25
Short variable declarationvar x, y int = 10, 20
Multiple variable declarationvar (
name = "Alice"
age = 30
)
Variable block declarationNotes:
Go is statically typed. Use := for new variables, = for existing ones
Constants
Basic SyntaxDeclare constants in Go
Syntax:
const NAME = value
const NAME type = value
Examples:
const Pi = 3.14159
Simple constantconst MaxUsers int = 100
Typed constantconst (
Red = "red"
Green = "green"
Blue = "blue"
)
Constant blockconst (
A = iota // 0
B // 1
C // 2
)
Using iota for enumerationNotes:
Constants are computed at compile time and cannot be changed
Functions
Basic SyntaxDefine 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 returnfunc add(a, b int) int {
return a + b
}
Function with multiple parametersfunc divide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("division by zero")
}
return a / b, nil
}
Function with multiple return valuesfunc sum(nums ...int) int {
total := 0
for _, num := range nums {
total += num
}
return total
}
Variadic functionNotes:
Functions are first-class citizens and can return multiple values
Structs
Basic SyntaxDefine custom types using structs
Syntax:
type Name struct {
field1 type1
field2 type2
}
Examples:
type Person struct {
Name string
Age int
}
Basic struct definitionp := Person{Name: "Alice", Age: 30}
Struct initializationtype User struct {
ID int `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
}
Struct with JSON tagsfunc (p Person) Greet() string {
return "Hello, I'm " + p.Name
}
Method on structNotes:
Structs are value types and support methods and tags for serialization
Packages
Basic SyntaxOrganize code using packages
Syntax:
package name
import "package/path"
Examples:
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
Main package with importimport (
"fmt"
"os"
"time"
)
Multiple importsimport (
f "fmt"
_ "github.com/lib/pq"
)
Import alias and blank importpackage utils
// Exported function (capitalized)
func FormatName(s string) string {
return strings.Title(s)
}
// unexported function
func helper() {}
Package with exported/unexported functionsNotes:
Capitalized names are exported (public), lowercase names are private to package
Arrays & Slices
Data TypesWork 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 initializationslice := []string{"apple", "banana", "cherry"}
Slice literalnums := make([]int, 5, 10)
fmt.Println(len(nums), cap(nums)) // 5, 10
Creating slice with makeslice = append(slice, "date")
slice = append(slice, "elderberry", "fig")
Appending to slicesubSlice := slice[1:3] // elements 1 and 2
Slice operationsNotes:
Arrays have fixed size, slices are dynamic. Use slices for most cases
Maps
Data TypesUse 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 literalm := make(map[string]int)
m["key"] = 42
Creating and setting map valuesvalue, ok := m["key"]
if ok {
fmt.Println("Found:", value)
}
Checking if key existsdelete(m, "key") // Remove key-value pair
Deleting from mapfor key, value := range ages {
fmt.Printf("%s: %d\n", key, value)
}
Iterating over mapNotes:
Maps are reference types and must be initialized before use
Interfaces
Data TypesDefine interfaces for polymorphism
Syntax:
type InterfaceName interface {
Method1() returnType
Method2(param type) returnType
}
Examples:
type Writer interface {
Write([]byte) (int, error)
}
Simple interface definitiontype Shape interface {
Area() float64
Perimeter() float64
}
Interface with multiple methodsfunc (r Rectangle) Area() float64 {
return r.Width * r.Height
}
// Rectangle implements Shape interface
Implementing interface implicitlyvar s Shape = Rectangle{Width: 10, Height: 5}
area := s.Area() // Polymorphism
Using interface for polymorphismfunc 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 TypesWork 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 usagefunc increment(x *int) {
*x++
}
num := 5
increment(&num)
fmt.Println(num) // 6
Passing pointer to functionp := new(int) // Allocates memory, returns pointer
*p = 100
Using new() to allocate memorytype Person struct {
Name string
}
p := &Person{Name: "Alice"}
Pointer to structNotes:
Go has pointers but no pointer arithmetic. Use & to get address, * to dereference
Goroutines
ConcurrencyRun functions concurrently using goroutines
Syntax:
go function()
go func() { }()
Examples:
go fmt.Println("Hello from goroutine")
Simple goroutinego func() {
fmt.Println("Anonymous goroutine")
}()
Anonymous function goroutinefor i := 0; i < 3; i++ {
go func(id int) {
fmt.Printf("Worker %d\n", id)
}(i)
}
Multiple goroutines with parametersvar wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
fmt.Println("Work done")
}()
wg.Wait()
Using WaitGroup to wait for goroutinesNotes:
Goroutines are lightweight threads managed by Go runtime. Always ensure proper synchronization
Channels
ConcurrencyCommunicate 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 communicationch := make(chan int, 2) // Buffered channel
ch <- 1
ch <- 2
fmt.Println(<-ch, <-ch)
Buffered channelch := make(chan int)
close(ch)
val, ok := <-ch
fmt.Println(val, ok) // 0, false
Closing channels and checking statusfor val := range ch {
fmt.Println(val)
}
Ranging over channelch := make(chan<- int) // Send-only
ch2 := make(<-chan int) // Receive-only
Directional channelsNotes:
Channels enable safe communication between goroutines. Use buffered channels to avoid blocking
Select Statement
ConcurrencyHandle 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 timeoutselect {
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 defaultfor {
select {
case msg := <-ch:
process(msg)
case <-quit:
return
}
}
Select in infinite loopNotes:
Select lets goroutines wait on multiple channel operations. Default case makes it non-blocking
Mutex
ConcurrencySynchronize 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 operationsvar mu sync.RWMutex
func read() {
mu.RLock()
defer mu.RUnlock()
// Read operation
}
Read-write mutex for concurrent readsvar once sync.Once
func initialize() {
once.Do(func() {
fmt.Println("Initialized once")
})
}
Using sync.Once for one-time initializationNotes:
Always use defer to unlock mutex. RWMutex allows multiple readers or one writer
Error Handling
Error HandlingHandle 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 checkingimport "errors"
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("division by zero")
}
return a / b, nil
}
Creating custom errorsimport "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 typeerr := someFunction()
if err != nil {
return fmt.Errorf("failed to process: %w", err)
}
Error wrapping with fmt.ErrorfNotes:
Errors are values, not exceptions. Always check and handle errors explicitly
Panic & Recover
Error HandlingHandle 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 panicif x < 0 {
panic("x cannot be negative")
}
Using panic for unrecoverable errorsfunc 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 deferNotes:
Use panic for programmer errors, not for normal error handling. Recover only works inside deferred functions
HTTP Server
HTTP & WebCreate 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 serverfunc 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 endpointmux := http.NewServeMux()
mux.HandleFunc("/users", usersHandler)
mux.HandleFunc("/posts", postsHandler)
http.ListenAndServe(":8080", mux)
Using custom mux for routingserver := &http.Server{
Addr: ":8080",
Handler: mux,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
}
server.ListenAndServe()
HTTP server with timeoutsNotes:
net/http package provides a complete HTTP server implementation
HTTP Client
HTTP & WebMake 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 requestdata := strings.NewReader(`{"name": "John"}`)
resp, err := http.Post("https://api.example.com/users", "application/json", data)
POST request with JSONclient := &http.Client{
Timeout: 30 * time.Second,
}
resp, err := client.Get(url)
HTTP client with timeoutreq, _ := 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 headersNotes:
Always close response body and handle timeouts for production code
JSON Handling
HTTP & WebWork 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 JSONjsonStr := `{"id": 1, "name": "Bob"}`
var user User
err := json.Unmarshal([]byte(jsonStr), &user)
Unmarshal JSON to structencoder := json.NewEncoder(w) // w is io.Writer
encoder.Encode(user)
Stream encoding to writerdecoder := json.NewDecoder(r) // r is io.Reader
var user User
err := decoder.Decode(&user)
Stream decoding from readerNotes:
Use struct tags to control JSON field names. Marshal/Unmarshal for []byte, Encode/Decode for streams
Unit Tests
TestingWrite 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 testfunc TestDivide(t *testing.T) {
_, err := Divide(10, 0)
if err == nil {
t.Error("Expected error for division by zero")
}
}
Testing error conditionsfunc 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 testsNotes:
Run tests with 'go test'. Test files must end with _test.go
Benchmarks
TestingWrite 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 benchmarkfunc 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 resetfunc 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 timingNotes:
Run benchmarks with 'go test -bench=.'. Use b.ResetTimer() to exclude setup time
Go Modules
Package ManagementManage 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 modulego get github.com/gin-gonic/gin
Add dependencygo get github.com/gin-gonic/gin@v1.9.1
Add specific versiongo mod tidy
Clean up dependenciesgo mod download
Download dependenciesgo list -m all
List all dependenciesNotes:
Go modules are the official dependency management system since Go 1.11
Go CLI Commands
Package ManagementCommon Go command line operations
Syntax:
go command [arguments]
Examples:
go run main.go
Run Go program directlygo build -o myapp main.go
Build executablego install github.com/user/tool@latest
Install Go programgo test ./...
Run all tests recursivelygo test -v -cover
Run tests with verbose output and coveragego fmt ./...
Format all Go filesgo vet ./...
Static analysis of codeNotes:
Go CLI provides comprehensive tooling for development, testing, and deployment
Gin Framework
Popular LibrariesHTTP 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 serverr.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 bindingr.GET("/users/:id", func(c *gin.Context) {
id := c.Param("id")
c.JSON(200, gin.H{"user_id": id})
})
URL parametersr.Use(gin.Logger())
r.Use(gin.Recovery())
r.Use(corsMiddleware())
Middleware usageNotes:
Gin is a high-performance HTTP framework with minimal memory footprint
Echo Framework
Popular LibrariesMinimalist 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 servere.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 bindinge.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 Echoe.Use(middleware.Logger())
e.Use(middleware.Recover())
e.Use(middleware.CORS())
Echo middlewareNotes:
Echo is optimized for high performance and extensibility with rich middleware ecosystem
GORM ORM
Popular LibrariesObject 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 migrationuser := User{Name: "Alice", Email: "alice@example.com"}
result := db.Create(&user)
Create recordvar user User
db.First(&user, 1) // find by primary key
db.First(&user, "name = ?", "Alice") // find by condition
Query recordsdb.Model(&user).Update("name", "Bob")
db.Model(&user).Updates(User{Name: "Bob", Age: 30})
Update recordsvar users []User
db.Where("age > ?", 18).Find(&users)
db.Order("age desc").Limit(10).Find(&users)
Advanced queriesNotes:
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
Type | Example | Zero Value | Description |
---|---|---|---|
int | 42 | 0 | Platform-dependent integer |
string | "hello" | "" | UTF-8 string |
bool | true | false | Boolean values |
[]int | [1, 2, 3] | nil | Dynamic array |
map[string]int | {"a": 1} | nil | Hash table |
chan int | make(chan int) | nil | Communication channel |
*int | &x | nil | Pointer to int |
interface{} | any value | nil | Empty interface (any type) |
Common Operations
value, ok := x.(Type) - Type assertion
reflect.TypeOf(x) - Get type at runtime
new(Type) - Allocate and return pointer
make([]Type, len, cap) - Create slices, maps, channels
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