
Go Cheatsheet
23 of 23 code examples
Hello World
Basic Go program structure
Basicspackage main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
Variables
Variable declarations
Basics// Variable declaration
var name string = "John"
var age int = 30
// Type inference
var city = "New York"
var score = 95.5
// Short declaration (inside functions)
country := "USA"
temperature := 25.3
// Multiple variables
var x, y int = 10, 20
a, b := "hello", "world"
// Constants
const Pi = 3.14159
const MaxUsers = 1000
Data Types
Basic data types
Basics// Basic types
var isActive bool = true
var count int = 42
var price float64 = 19.99
var message string = "Hello"
// Integer types
var a int = 42 // platform-dependent
var b int32 = 100
var c int64 = 1000
var d uint = 50 // unsigned
// Complex numbers
var comp complex128 = complex(2, 3)
// Byte and rune
var ch byte = 'A' // alias for uint8
var r rune = '世' // alias for int32
Functions
Function declarations
Functions// Basic function
func greet(name string) string {
return "Hello, " + name
}
// Multiple parameters and return values
func calculate(a, b int) (int, int) {
sum := a + b
product := a * b
return sum, product
}
// Named return values
func divide(a, b float64) (result float64, err error) {
if b == 0 {
return 0, fmt.Errorf("cannot divide by zero")
}
result = a / b
return
}
// Variadic function
func sum(numbers ...int) int {
total := 0
for _, num := range numbers {
total += num
}
return total
}
// Function as parameter
func apply(fn func(int) int, x int) int {
return fn(x)
}
Control Structures
If, for, switch statements
Basics// If statement
if age >= 18 {
fmt.Println("Adult")
} else {
fmt.Println("Minor")
}
// If with initialization
if score := getScore(); score > 90 {
fmt.Println("Excellent!")
}
// For loop
for i := 0; i < 10; i++ {
fmt.Println(i)
}
// While-like loop
count := 0
for count < 5 {
fmt.Println(count)
count++
}
// Infinite loop
for {
// break to exit
break
}
// Switch statement
switch day {
case "Monday":
fmt.Println("Start of week")
case "Friday":
fmt.Println("Weekend soon!")
default:
fmt.Println("Regular day")
}
Arrays & Slices
Arrays and dynamic slices
Data Structures// Arrays (fixed size)
var numbers [5]int = [5]int{1, 2, 3, 4, 5}
names := [3]string{"Alice", "Bob", "Charlie"}
// Slices (dynamic arrays)
var scores []int = []int{85, 90, 78}
grades := make([]int, 0, 10) // length 0, capacity 10
// Slice operations
scores = append(scores, 95) // Append
sub := scores[1:3] // Slice
copy(sub, scores) // Copy
// Iterating slices
for index, value := range scores {
fmt.Printf("Index %d: %d\n", index, value)
}
// Common slice functions
len(scores) // Length
cap(scores) // Capacity
scores[0] // Access element
Maps
Key-value collections
Data Structures// Map declaration
ages := make(map[string]int)
ages["Alice"] = 30
ages["Bob"] = 25
// Literal initialization
scores := map[string]int{
"Alice": 95,
"Bob": 87,
}
// Access and check
score, exists := scores["Charlie"]
if exists {
fmt.Println("Score:", score)
}
// Delete
delete(scores, "Bob")
// Iteration
for name, score := range scores {
fmt.Printf("%s: %d\n", name, score)
}
// Map functions
len(scores) // Number of elements
Structs
Custom types and methods
Data Structures// Struct definition
type Person struct {
Name string
Age int
Email string
}
// Creating instances
p1 := Person{"Alice", 30, "alice@example.com"}
p2 := Person{
Name: "Bob",
Age: 25,
Email: "bob@example.com",
}
// Methods
func (p Person) Greet() string {
return "Hello, " + p.Name
}
// Pointer receiver method
func (p *Person) Birthday() {
p.Age++
}
// Embedded structs
type Employee struct {
Person
Department string
Salary float64
}
// Using embedded struct
emp := Employee{
Person: Person{"Charlie", 35, "charlie@company.com"},
Department: "Engineering",
Salary: 75000,
}
Interfaces
Interface types and polymorphism
OOP// Interface definition
type Shape interface {
Area() float64
Perimeter() float64
}
// Struct implementing interface
type Rectangle struct {
Width, Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func (r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}
// Another implementation
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return math.Pi * c.Radius * c.Radius
}
func (c Circle) Perimeter() float64 {
return 2 * math.Pi * c.Radius
}
// Using interface
func printShapeInfo(s Shape) {
fmt.Printf("Area: %.2f, Perimeter: %.2f\n", s.Area(), s.Perimeter())
}
// Empty interface (any type)
func printValue(v interface{}) {
fmt.Printf("Value: %v, Type: %T\n", v, v)
}
Error Handling
Go error handling patterns
Error Handling// Basic error handling
result, err := divide(10, 0)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Result:", result)
// Custom error type
type ValidationError struct {
Field string
Message string
}
func (e ValidationError) Error() string {
return fmt.Sprintf("%s: %s", e.Field, e.Message)
}
// Error checking helper
func processFile(filename string) error {
file, err := os.Open(filename)
if err != nil {
return fmt.Errorf("failed to open file: %w", err)
}
defer file.Close()
// Process file...
return nil
}
// Multiple error handling
if err := processFile("data.txt"); err != nil {
var valErr ValidationError
if errors.As(err, &valErr) {
fmt.Println("Validation error:", valErr)
} else {
fmt.Println("Other error:", err)
}
}
Concurrency - Goroutines
Lightweight threads
Concurrency// Basic goroutine
go func() {
fmt.Println("Running in goroutine")
}()
// Goroutine with parameters
for i := 0; i < 5; i++ {
go func(n int) {
fmt.Printf("Goroutine %d\n", n)
}(i)
}
// Wait for goroutines to complete
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
time.Sleep(time.Second)
fmt.Printf("Task %d completed\n", id)
}(i)
}
wg.Wait()
fmt.Println("All goroutines completed")
Concurrency - Channels
Communication between goroutines
Concurrency// Creating channels
messages := make(chan string)
buffered := make(chan int, 10) // buffered channel
// Sending and receiving
go func() {
messages <- "hello"
}()
msg := <-messages
fmt.Println(msg)
// Channel with select
select {
case msg := <-messages:
fmt.Println("Received:", msg)
case <-time.After(time.Second):
fmt.Println("Timeout")
}
// Range over channel
go func() {
for i := 0; i < 5; i++ {
buffered <- i
}
close(buffered)
}()
for num := range buffered {
fmt.Println("Received:", num)
}
// Channel directions
func producer(ch chan<- int) { // send-only
ch <- 42
}
func consumer(ch <-chan int) { // receive-only
value := <-ch
fmt.Println(value)
}
Concurrency - Mutex
Synchronization with mutex
Concurrency// Safe counter with mutex
type SafeCounter struct {
mu sync.Mutex
value int
}
func (c *SafeCounter) Increment() {
c.mu.Lock()
defer c.mu.Unlock()
c.value++
}
func (c *SafeCounter) Value() int {
c.mu.Lock()
defer c.mu.Unlock()
return c.value
}
// Using the safe counter
var counter SafeCounter
var wg sync.WaitGroup
for i := 0; i < 1000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
counter.Increment()
}()
}
wg.Wait()
fmt.Println("Final count:", counter.Value())
// RWMutex for read-heavy workloads
type Config struct {
mu sync.RWMutex
data map[string]string
}
func (c *Config) Get(key string) string {
c.mu.RLock()
defer c.mu.RUnlock()
return c.data[key]
}
func (c *Config) Set(key, value string) {
c.mu.Lock()
defer c.mu.Unlock()
c.data[key] = value
}
File Operations
Reading and writing files
I/O// Reading entire file
content, err := os.ReadFile("data.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(content))
// Writing file
data := []byte("Hello, World!")
err := os.WriteFile("output.txt", data, 0644)
if err != nil {
log.Fatal(err)
}
// Reading line by line
file, err := os.Open("data.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
// Writing with buffered writer
file, err := os.Create("output.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
writer := bufio.NewWriter(file)
fmt.Fprintln(writer, "Hello, World!")
writer.Flush()
JSON Operations
JSON encoding and decoding
Data Formats// JSON encoding
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
person := Person{"Alice", 30}
jsonData, err := json.Marshal(person)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(jsonData))
// JSON decoding
var decodedPerson Person
err = json.Unmarshal(jsonData, &decodedPerson)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", decodedPerson)
// Streaming JSON encoder
encoder := json.NewEncoder(os.Stdout)
encoder.Encode(person)
// Custom JSON marshaling
func (p Person) MarshalJSON() ([]byte, error) {
type Alias Person
return json.Marshal(&struct {
*Alias
Formatted string `json:"formatted"`
}{
Alias: (*Alias)(&p),
Formatted: fmt.Sprintf("%s (%d years)", p.Name, p.Age),
})
}
HTTP Server
Building web servers
Web// Basic HTTP server
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
})
http.HandleFunc("/api/users", func(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
users := []string{"Alice", "Bob"}
json.NewEncoder(w).Encode(users)
case "POST":
var user struct{ Name string }
json.NewDecoder(r.Body).Decode(&user)
fmt.Fprintf(w, "Created user: %s", user.Name)
default:
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
})
log.Println("Server starting on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
// With middleware
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Printf("%s %s", r.Method, r.URL.Path)
next.ServeHTTP(w, r)
})
}
// Using middleware
mux := http.NewServeMux()
mux.HandleFunc("/", handler)
wrappedMux := loggingMiddleware(mux)
HTTP Client
Making HTTP requests
Web// GET request
resp, err := http.Get("https://api.example.com/users")
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(body))
// POST request with JSON
user := map[string]string{"name": "Alice"}
jsonData, _ := json.Marshal(user)
resp, err := http.Post(
"https://api.example.com/users",
"application/json",
bytes.NewBuffer(jsonData),
)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
// Custom client with timeout
client := &http.Client{
Timeout: 10 * time.Second,
}
req, err := http.NewRequest("GET", "https://api.example.com/data", nil)
if err != nil {
log.Fatal(err)
}
req.Header.Add("Authorization", "Bearer token")
resp, err := client.Do(req)
Testing
Writing tests in Go
Testing// Basic test
func TestAdd(t *testing.T) {
result := Add(2, 3)
expected := 5
if result != expected {
t.Errorf("Add(2, 3) = %d; want %d", result, expected)
}
}
// Table-driven tests
func TestMultiply(t *testing.T) {
tests := []struct {
a, b int
expected int
}{
{2, 3, 6},
{0, 5, 0},
{-2, 3, -6},
}
for _, test := range tests {
result := Multiply(test.a, test.b)
if result != test.expected {
t.Errorf("Multiply(%d, %d) = %d; want %d",
test.a, test.b, result, test.expected)
}
}
}
// Benchmark test
func BenchmarkFibonacci(b *testing.B) {
for i := 0; i < b.N; i++ {
Fibonacci(20)
}
}
// Example test (appears in documentation)
func ExampleAdd() {
sum := Add(1, 2)
fmt.Println(sum)
// Output: 3
}
Context
Context for cancellation and timeouts
Concurrency// Context with timeout
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
// Use context in HTTP request
req, err := http.NewRequestWithContext(ctx, "GET", "http://example.com", nil)
if err != nil {
log.Fatal(err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
// Context with cancellation
ctx, cancel := context.WithCancel(context.Background())
go func() {
time.Sleep(2 * time.Second)
cancel() // Cancel the context after 2 seconds
}()
// Check context in long-running operation
select {
case <-time.After(10 * time.Second):
fmt.Println("Operation completed")
case <-ctx.Done():
fmt.Println("Operation cancelled:", ctx.Err())
}
// Context with values
type key string
const userKey key = "user"
ctx := context.WithValue(context.Background(), userKey, "alice")
if user, ok := ctx.Value(userKey).(string); ok {
fmt.Println("User:", user)
}
Defer, Panic, Recover
Error recovery mechanisms
Error Handling// Defer for cleanup
func processFile(filename string) error {
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close() // Always close the file
// Process file...
return nil
}
// Multiple defers (LIFO order)
func example() {
defer fmt.Println("First defer")
defer fmt.Println("Second defer")
fmt.Println("Function body")
// Output: Function body, Second defer, First defer
}
// Panic and recover
func safeDivide(a, b int) (result int, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic occurred: %v", r)
}
}()
if b == 0 {
panic("division by zero")
}
return a / b, nil
}
// Using recover
result, err := safeDivide(10, 0)
if err != nil {
fmt.Println("Error:", err)
}
Package Management
Go modules and imports
Packages// go.mod file example
module github.com/username/myproject
go 1.21
require (
github.com/gorilla/mux v1.8.0
github.com/lib/pq v1.10.9
)
// Importing packages
import (
"fmt"
"net/http"
"encoding/json"
"github.com/gorilla/mux"
"github.com/lib/pq"
)
// Custom package structure
// myproject/
// go.mod
// main.go
// pkg/
// utils/
// math.go
// internal/
// config/
// config.go
// In math.go
package utils
func Add(a, b int) int {
return a + b
}
// Using custom package
import "github.com/username/myproject/pkg/utils"
func main() {
result := utils.Add(2, 3)
fmt.Println(result)
}
Real-World: REST API
Complete REST API example
Real Worldpackage main
import (
"encoding/json"
"log"
"net/http"
"strconv"
"github.com/gorilla/mux"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
var users = []User{
{ID: 1, Name: "Alice", Email: "alice@example.com"},
{ID: 2, Name: "Bob", Email: "bob@example.com"},
}
func getUsers(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(users)
}
func getUser(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
id, _ := strconv.Atoi(params["id"])
for _, user := range users {
if user.ID == id {
json.NewEncoder(w).Encode(user)
return
}
}
http.Error(w, "User not found", http.StatusNotFound)
}
func createUser(w http.ResponseWriter, r *http.Request) {
var user User
if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
user.ID = len(users) + 1
users = append(users, user)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(user)
}
func main() {
r := mux.NewRouter()
r.HandleFunc("/users", getUsers).Methods("GET")
r.HandleFunc("/users/{id}", getUser).Methods("GET")
r.HandleFunc("/users", createUser).Methods("POST")
log.Println("Server starting on :8080")
log.Fatal(http.ListenAndServe(":8080", r))
}
Real-World: Worker Pool
Concurrent worker pattern
Real Worldpackage main
import (
"fmt"
"sync"
"time"
)
type Job struct {
ID int
Data string
}
type Result struct {
JobID int
Output string
Err error
}
func worker(id int, jobs <-chan Job, results chan<- Result, wg *sync.WaitGroup) {
defer wg.Done()
for job := range jobs {
fmt.Printf("Worker %d processing job %d\n", id, job.ID)
// Simulate work
time.Sleep(time.Second)
result := Result{
JobID: job.ID,
Output: fmt.Sprintf("Processed: %s", job.Data),
}
results <- result
}
}
func main() {
const numWorkers = 3
const numJobs = 10
jobs := make(chan Job, numJobs)
results := make(chan Result, numJobs)
var wg sync.WaitGroup
// Start workers
for i := 1; i <= numWorkers; i++ {
wg.Add(1)
go worker(i, jobs, results, &wg)
}
// Send jobs
for i := 1; i <= numJobs; i++ {
jobs <- Job{
ID: i,
Data: fmt.Sprintf("data-%d", i),
}
}
close(jobs)
// Wait for workers to complete
go func() {
wg.Wait()
close(results)
}()
// Collect results
for result := range results {
if result.Err != nil {
fmt.Printf("Job %d failed: %v\n", result.JobID, result.Err)
} else {
fmt.Printf("Job %d result: %s\n", result.JobID, result.Output)
}
}
fmt.Println("All jobs completed")
}