Go Cheatsheet
Go (Golang) Cheatsheet
A quick-reference guide for essential and advanced Go concepts, covering types, slices, maps, pointers, interfaces, concurrency primitives, and the Go toolchain.
Variables & Constants
package main
import "fmt"
func main() {
// 1. Variable Declarations
var x int = 10 // Explicit type
var y = "hello" // Inferred type
z := true // Short declaration operator (inside functions only)
// Multiple assignments
a, b := 1, 2
// 2. Constants
const Pi = 3.14159 // Compile-time resolved constant
const (
StatusOk = 200
StatusFail = 500
)
}
Control Flow
// 1. Conditionals (no parentheses, braces required)
if x > 10 {
fmt.Println("Greater")
} else {
fmt.Println("Less/Equal")
}
// Inline statement evaluation (scope is restricted to the if/else block)
if val := calculate(); val > 0 {
fmt.Println(val)
}
// 2. For Loops (Go's only loop structure!)
for i := 0; i < 5; i++ { // Standard loop
fmt.Println(i)
}
for x < 100 { // While-style loop
x += 10
}
for { // Infinite loop
break
}
// 3. Switch Statement (No implicit fallthrough, break is automatic)
switch x {
case 1, 2:
fmt.Println("One or Two")
case 10:
fmt.Println("Ten")
default:
fmt.Println("Default")
}
Slices & Maps
// 1. Slices (Dynamically sized arrays)
var s []int // nil slice
s = append(s, 1, 2) // Add elements dynamically
s2 := make([]int, 5, 10) // Slice with length 5 and capacity 10
s3 := []string{"a", "b", "c"} // Slice literal
// Slicing operations
subset := s3[1:3] // ["b", "c"] (index 1 to 2)
// Iterating with Range
for index, value := range s3 {
fmt.Printf("%d: %s\n", index, value)
}
// 2. Maps (Hash tables)
ages := make(map[string]int) // Create map
ages["Alice"] = 30
// Map literal
userRoles := map[string]string{
"admin": "read,write",
"user": "read",
}
// Check if key exists (comma ok idiom)
role, ok := userRoles["guest"] // ok is false if key is missing
// Delete key
delete(userRoles, "user")
Functions, Pointers & defer
// Multiple return values and named returns
func divide(a, b float64) (result float64, err error) {
if b == 0 {
return 0, fmt.Errorf("division by zero")
}
result = a / b
return result, nil // Naked return of named variables
}
// Pointers (* = value at pointer, & = address of value)
func updateValue(ptr *int) {
*ptr = 20 // Dereference and assign new value
}
// defer (Delays execution of function until parent function returns - useful for resource cleanup)
func readFile() {
file, _ := os.Open("data.txt")
defer file.Close() // Closed automatically at end of function
// ... read file ...
}
Structs & Methods
type User struct {
ID int
Name string
Email string
}
// Value Receiver Method (Operates on copy of struct)
func (u User) Greet() string {
return "Hello, " + u.Name
}
// Pointer Receiver Method (Operates on original struct, can modify fields)
func (u *User) UpdateEmail(newEmail string) {
u.Email = newEmail
}
// Instantiate struct
u := User{ID: 1, Name: "Alice", Email: "a@b.com"}
u.UpdateEmail("new@b.com") // Syntax shorthand for (&u).UpdateEmail(...)
Interfaces
// Defining an Interface
type Shape interface {
Area() float64
Perimeter() float64
}
type Circle struct {
Radius float64
}
// Implementing an Interface (Go interfaces are implemented implicitly!)
func (c Circle) Area() float64 {
return 3.14 * c.Radius * c.Radius
}
func (c Circle) Perimeter() float64 {
return 2 * 3.14 * c.Radius
}
// Empty Interface (Any type implements the empty interface)
var anyValue interface{} = "hello"
Concurrency (Goroutines & Channels)
func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
results <- j * 2 // Send result to channel
}
}
func main() {
// 1. Goroutine (Lightweight thread managed by Go runtime)
go fmt.Println("Hello from background")
// 2. Channels (Thread-safe message pipes)
ch := make(chan string)
go func() { ch <- "ping" }() // Send to channel
msg := <-ch // Receive from channel
// 3. Buffered Channels
bufCh := make(chan int, 2) // Buffer size 2 (does not block sender until full)
// 4. select (Blocks until one of its channel cases can execute)
select {
case msg1 := <-ch:
fmt.Println("Received", msg1)
case bufCh <- 10:
fmt.Println("Sent to buffer")
default:
fmt.Println("No channel active")
}
}
Concurrency Sync Primitives
import "sync"
// 1. WaitGroup (Block execution thread until multiple goroutines finish)
var wg sync.WaitGroup
for i := 1; i <= 3; i++ {
wg.Add(1) // Increment WaitGroup counter
go func(id int) {
defer wg.Done() // Decrement counter when finished
fmt.Println("Job", id)
}(i)
}
wg.Wait() // Block until counter reaches 0
// 2. Mutex (Ensure only one goroutine accesses critical section at a time)
var (
mu sync.Mutex
count = 0
)
func increment() {
mu.Lock()
defer mu.Unlock()
count++
}
Error Handling
import "errors"
// 1. Returning Errors
func findUser(id int) (*User, error) {
if id <= 0 {
return nil, errors.New("invalid user ID") // Standard error creation
}
return &User{ID: id}, nil
}
// 2. Custom Error Structures
type QueryError struct {
Query string
Err error
}
func (e *QueryError) Error() string {
return fmt.Sprintf("Query %q failed: %v", e.Query, e.Err)
}
Go CLI Toolchain
go mod init <module_name> # Initialize a new Go module (generates go.mod)
go run main.go # Compile and run the specified Go file immediately
go build # Compile active directory package into executable binary
go build -o app_bin # Compile and output binary using a custom filename
go test # Run all unit tests (*_test.go) in the active folder
go test -v # Run tests in verbose mode (list individual run outcomes)
go get <package_path> # Download and add a remote dependency to go.mod
go fmt # Automatically format all Go files in active package
go vet # Run static analysis tool to find common semantic bugs