Go (Golang) Cheatsheet
Basics
Hello World
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
Running Go Programs
go run main.go # Run directly
go build main.go # Compile to binary
go install # Install package
Variables and Constants
Variable Declaration
// Explicit type
var name string = "John"
// Type inference
var age = 30
// Short declaration (inside functions only)
city := "New York"
// Multiple variables
var (
firstName string = "Jane"
lastName string = "Doe"
userAge int = 25
)
// Multiple assignment
x, y := 10, 20
Constants
const Pi = 3.14159
const (
StatusOK = 200
StatusNotFound = 404
)
// iota - constant generator
const (
Sunday = iota // 0
Monday // 1
Tuesday // 2
)
Data Types
Basic Types
// Integers
int, int8, int16, int32, int64
uint, uint8, uint16, uint32, uint64
// Floating point
float32, float64
// Complex numbers
complex64, complex128
// Boolean
bool // true or false
// String
string
// Byte (alias for uint8)
byte
// Rune (alias for int32, represents Unicode code point)
rune
Type Conversion
var i int = 42
var f float64 = float64(i)
var u uint = uint(f)
str := string(65) // "A"
Zero Values
var i int // 0
var f float64 // 0.0
var b bool // false
var s string // ""
var p *int // nil
Operators
Arithmetic
+ // Addition
- // Subtraction
* // Multiplication
/ // Division
% // Modulus
++ // Increment
-- // Decrement
Comparison
== // Equal to
!= // Not equal to
< // Less than
> // Greater than
<= // Less than or equal to
>= // Greater than or equal to
Logical
&& // Logical AND
|| // Logical OR
! // Logical NOT
Bitwise
& // AND
| // OR
^ // XOR
<< // Left shift
>> // Right shift
Control Structures
If-Else
if x > 0 {
fmt.Println("Positive")
} else if x < 0 {
fmt.Println("Negative")
} else {
fmt.Println("Zero")
}
// If with short statement
if err := doSomething(); err != nil {
fmt.Println("Error:", err)
}
Switch
switch day {
case "Monday":
fmt.Println("Start of week")
case "Friday":
fmt.Println("End of week")
default:
fmt.Println("Midweek")
}
// Switch without condition (like if-else chain)
switch {
case x < 0:
fmt.Println("Negative")
case x > 0:
fmt.Println("Positive")
default:
fmt.Println("Zero")
}
// Type switch
switch v := i.(type) {
case int:
fmt.Println("Integer:", v)
case string:
fmt.Println("String:", v)
default:
fmt.Println("Unknown type")
}
Loops
// Traditional for loop
for i := 0; i < 10; i++ {
fmt.Println(i)
}
// While-style loop
for x < 100 {
x++
}
// Infinite loop
for {
// Loop forever
break // Exit loop
}
// Range loop
numbers := []int{1, 2, 3, 4, 5}
for index, value := range numbers {
fmt.Println(index, value)
}
// Ignore index
for _, value := range numbers {
fmt.Println(value)
}
// Only index
for index := range numbers {
fmt.Println(index)
}
Defer, Panic, Recover
// Defer - executes after function returns
defer fmt.Println("World")
fmt.Println("Hello") // Prints: Hello, then World
// Panic - stops normal execution
panic("Something went wrong!")
// Recover - regain control after panic
func safeFunction() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered:", r)
}
}()
panic("Oops!")
}
Functions
Basic Function
func add(x int, y int) int {
return x + y
}
// Short form when parameters share type
func multiply(x, y int) int {
return x * y
}
Multiple Return Values
func divide(x, y float64) (float64, error) {
if y == 0 {
return 0, fmt.Errorf("division by zero")
}
return x / y, nil
}
result, err := divide(10, 2)
Named Return Values
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return // Naked return
}
Variadic Functions
func sum(numbers ...int) int {
total := 0
for _, num := range numbers {
total += num
}
return total
}
sum(1, 2, 3, 4, 5)
Anonymous Functions & Closures
// Anonymous function
func() {
fmt.Println("Anonymous")
}()
// Closure
func counter() func() int {
count := 0
return func() int {
count++
return count
}
}
c := counter()
fmt.Println(c()) // 1
fmt.Println(c()) // 2
Arrays and Slices
Arrays (Fixed Size)
var arr [5]int
arr[0] = 1
// Array literal
primes := [5]int{2, 3, 5, 7, 11}
// Auto count
arr := [...]int{1, 2, 3, 4, 5}
Slices (Dynamic Size)
// Create slice
var s []int
s = []int{1, 2, 3, 4, 5}
// Make slice with length and capacity
s := make([]int, 5) // len=5, cap=5
s := make([]int, 0, 5) // len=0, cap=5
// Slice from array
arr := [5]int{1, 2, 3, 4, 5}
slice := arr[1:4] // [2, 3, 4]
// Append to slice
s = append(s, 6)
s = append(s, 7, 8, 9)
// Copy slice
dest := make([]int, len(s))
copy(dest, s)
// Length and capacity
len(s)
cap(s)
Maps
Creating Maps
// Make map
var m map[string]int
m = make(map[string]int)
// Map literal
ages := map[string]int{
"Alice": 25,
"Bob": 30,
}
// Short form
m := make(map[string]int)
Map Operations
// Set value
m["key"] = 42
// Get value
value := m["key"]
// Check if key exists
value, ok := m["key"]
if ok {
fmt.Println("Key exists:", value)
}
// Delete key
delete(m, "key")
// Iterate over map
for key, value := range m {
fmt.Println(key, value)
}
// Length
len(m)
Structs
Defining and Using Structs
// Define struct
type Person struct {
Name string
Age int
City string
}
// Create instance
p1 := Person{Name: "Alice", Age: 30, City: "NYC"}
p2 := Person{"Bob", 25, "LA"} // In order
// Access fields
fmt.Println(p1.Name)
p1.Age = 31
// Pointer to struct
p := &Person{Name: "Charlie", Age: 35}
p.Age = 36 // Automatic dereferencing
// Anonymous struct
dog := struct {
Name string
Breed string
}{
Name: "Max",
Breed: "Labrador",
}
Embedded Structs
type Address struct {
Street string
City string
}
type Employee struct {
Name string
Address // Embedded struct
}
e := Employee{
Name: "John",
Address: Address{
Street: "123 Main St",
City: "Boston",
},
}
fmt.Println(e.City) // Direct access
Pointers
Pointer Basics
// Declare pointer
var p *int
// Get address
x := 42
p = &x
// Dereference pointer
fmt.Println(*p) // 42
*p = 21
fmt.Println(x) // 21
// New function
p := new(int)
*p = 100
Interfaces
Defining Interfaces
type Shape interface {
Area() float64
Perimeter() float64
}
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)
}
// Using interface
var s Shape = Rectangle{Width: 10, Height: 5}
fmt.Println(s.Area())
Empty Interface
// Can hold any type
var i interface{}
i = 42
i = "hello"
i = true
// Type assertion
value, ok := i.(string)
if ok {
fmt.Println("String:", value)
}
Common Interfaces
// Stringer
type Stringer interface {
String() string
}
// Error
type error interface {
Error() string
}
Methods
Methods on Structs
type Person struct {
Name string
Age int
}
// Value receiver
func (p Person) Greet() string {
return "Hello, " + p.Name
}
// Pointer receiver
func (p *Person) HaveBirthday() {
p.Age++
}
p := Person{Name: "Alice", Age: 30}
p.Greet()
p.HaveBirthday()
Error Handling
Creating Errors
import "errors"
// Simple error
err := errors.New("something went wrong")
// Formatted error
err := fmt.Errorf("invalid value: %d", value)
Custom Error Types
type MyError struct {
Code int
Message string
}
func (e *MyError) Error() string {
return fmt.Sprintf("Error %d: %s", e.Code, e.Message)
}
Error Handling Pattern
result, err := doSomething()
if err != nil {
return err // or handle it
}
// Use result
Concurrency
Goroutines
// Start goroutine
go func() {
fmt.Println("Running in goroutine")
}()
go myFunction()
// Wait for goroutines (basic)
time.Sleep(time.Second)
Channels
// Create channel
ch := make(chan int)
// Buffered channel
ch := make(chan int, 5)
// Send to channel
ch <- 42
// Receive from channel
value := <-ch
// Close channel
close(ch)
// Check if closed
value, ok := <-ch
if !ok {
fmt.Println("Channel closed")
}
Channel Patterns
// Range over channel
for value := range ch {
fmt.Println(value)
}
// Select statement
select {
case msg1 := <-ch1:
fmt.Println("Received from ch1:", msg1)
case msg2 := <-ch2:
fmt.Println("Received from ch2:", msg2)
case ch3 <- 42:
fmt.Println("Sent to ch3")
default:
fmt.Println("No communication")
}
WaitGroup
import "sync"
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
fmt.Println("Worker", id)
}(i)
}
wg.Wait()
Mutex
import "sync"
var (
mu sync.Mutex
counter int
)
mu.Lock()
counter++
mu.Unlock()
// RWMutex
var rwMu sync.RWMutex
rwMu.RLock() // Read lock
// Read operations
rwMu.RUnlock()
rwMu.Lock() // Write lock
// Write operations
rwMu.Unlock()
Packages
Importing Packages
import "fmt"
import "math"
// Multiple imports
import (
"fmt"
"math"
"strings"
)
// Alias
import f "fmt"
// Import for side effects
import _ "image/png"
Creating Packages
// File: mypackage/mypackage.go
package mypackage
// Exported (capitalized)
func PublicFunction() {
// Visible outside package
}
// Unexported (lowercase)
func privateFunction() {
// Only visible within package
}
Init Function
func init() {
// Runs automatically when package is imported
// Can have multiple init functions
}
File I/O
Reading Files
import (
"io/ioutil"
"os"
)
// Read entire file
data, err := ioutil.ReadFile("file.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(data))
// Read with os.Open
file, err := os.Open("file.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
Writing Files
// Write entire file
data := []byte("Hello, World!")
err := ioutil.WriteFile("file.txt", data, 0644)
// Write with os.Create
file, err := os.Create("file.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
writer := bufio.NewWriter(file)
writer.WriteString("Hello, World!\\n")
writer.Flush()
JSON
Encoding (Marshal)
import "encoding/json"
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
p := Person{Name: "Alice", Age: 30}
jsonData, err := json.Marshal(p)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(jsonData))
// Pretty print
jsonData, err := json.MarshalIndent(p, "", " ")
Decoding (Unmarshal)
jsonString := `{"name":"Bob","age":25}`
var p Person
err := json.Unmarshal([]byte(jsonString), &p)
if err != nil {
log.Fatal(err)
}
fmt.Println(p.Name, p.Age)
Testing
Basic Test
// File: mypackage_test.go
package mypackage
import "testing"
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 TestAdd(t *testing.T) {
tests := []struct {
name string
a, b int
expected int
}{
{"positive", 2, 3, 5},
{"negative", -1, -1, -2},
{"zero", 0, 5, 5},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := Add(tt.a, tt.b)
if result != tt.expected {
t.Errorf("got %d, want %d", result, tt.expected)
}
})
}
}
Benchmarks
func BenchmarkAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
Add(2, 3)
}
}
Running Tests
go test # Run tests
go test -v # Verbose
go test -cover # Coverage
go test -bench=. # Run benchmarks
Common Patterns
Constructor Pattern
func NewPerson(name string, age int) *Person {
return &Person{
Name: name,
Age: age,
}
}
Options Pattern
type Options struct {
Host string
Port int
}
type Option func(*Options)
func WithHost(host string) Option {
return func(o *Options) {
o.Host = host
}
}
func NewServer(opts ...Option) *Server {
options := &Options{
Host: "localhost",
Port: 8080,
}
for _, opt := range opts {
opt(options)
}
return &Server{options: options}
}
Context Pattern
import "context"
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
defer cancel()
ctx, cancel = context.WithTimeout(ctx, 5*time.Second)
ctx = context.WithValue(ctx, "key", "value")
Useful Commands
go run main.go # Run program
go build # Build binary
go install # Install binary
go test # Run tests
go fmt # Format code
go vet # Report suspicious constructs
go mod init module_name # Initialize module
go mod tidy # Clean up dependencies
go get package_name # Install package
go doc package_name # View documentation