Go (Golang) Cheat Sheet
A comprehensive quick reference for Go (Golang) covering variables, data types, control flow, functions, concurrency primitives, error handling, structs, interfaces, and the most-used standard library packages. Bookmark this page and keep it open while you code.
Table of Contents
Variables & Constants
| Pattern | Description | Example |
|---|---|---|
var declaration |
Declare with explicit type | var name string = "Alice" |
var with inference |
Type inferred from value | var age = 30 |
Short declaration := |
Declare and assign (inside functions only) | count := 42 |
| Multiple variables | Declare several at once | var x, y, z int = 1, 2, 3 |
| Var block | Group variable declarations | var ( |
const |
Immutable value (compile-time) | const Pi = 3.14159 |
const block |
Group constants | const ( |
iota |
Auto-incrementing constant generator | const ( |
| Zero values | Default value when not initialized | // int: 0, string: "", bool: false, pointer: nil |
| Type conversion | Explicit type casting (no implicit conversion) | f := float64(intVal) |
package main
const (
KB = 1024
MB = KB * 1024
GB = MB * 1024
)
func main() {
name := "Go" // short declaration (type inferred as string)
var version float64 = 1.22 // explicit type
year, month := 2024, "March" // multiple assignment
_ = version // blank identifier suppresses "unused" error
_ = year
_ = month
_ = name
}
Tip: Use
:= inside functions for concise declarations. Use var for package-level variables or when you need to declare without initializing.Data Types
| Type | Description | Zero Value |
|---|---|---|
bool |
Boolean true/false | false |
string |
UTF-8 encoded text (immutable) | "" |
int, int8, int16, int32, int64 |
Signed integers (int is platform-dependent: 32 or 64 bit) | 0 |
uint, uint8, uint16, uint32, uint64 |
Unsigned integers | 0 |
float32, float64 |
IEEE-754 floating point | 0.0 |
complex64, complex128 |
Complex numbers (real + imaginary) | (0+0i) |
byte |
Alias for uint8 |
0 |
rune |
Alias for int32 (represents a Unicode code point) |
0 |
uintptr |
Integer large enough to hold a pointer value | 0 |
var (
isReady bool = true
name string = "Gopher"
age int = 10
price float64 = 19.99
initial rune = 'G' // Unicode code point U+0047
data byte = 0xFF
z complex128 = 3 + 4i
)
// Type alias
type UserID int64
type Celsius float64
Control Flow
| Statement | Description | Example |
|---|---|---|
if / else |
Conditional branching (no parentheses needed) | if x > 10 { ... } else { ... } |
if with init |
Short statement before condition | if err := doWork(); err != nil { ... } |
for (classic) |
C-style for loop | for i := 0; i < 10; i++ { ... } |
for (while) |
Condition-only loop | for x < 100 { x *= 2 } |
for (infinite) |
Loop forever (break to exit) | for { ... } |
for range |
Iterate over slices, maps, strings, channels | for i, v := range slice { ... } |
switch |
Multi-way branching (no fallthrough by default) | switch day { case "Mon": ... } |
switch (no expr) |
Clean replacement for if/else chains | switch { case x > 0: ... } |
switch type |
Branch on interface type | switch v := i.(type) { case int: ... } |
select |
Wait on multiple channel operations | select { case msg := <-ch: ... } |
defer |
Schedule call to run when function returns (LIFO) | defer file.Close() |
break / continue |
Exit loop or skip to next iteration | if done { break } |
goto |
Jump to label (rarely used) | goto cleanup |
// if with init statement
if f, err := os.Open("file.txt"); err != nil {
log.Fatal(err)
} else {
defer f.Close()
// use f
}
// for range over a map
for key, value := range myMap {
fmt.Printf("%s: %v\n", key, value)
}
// switch with no expression
switch {
case score >= 90:
grade = "A"
case score >= 80:
grade = "B"
default:
grade = "C"
}
// select on channels
select {
case msg := <-ch1:
fmt.Println(msg)
case ch2 <- "ping":
fmt.Println("sent")
case <-time.After(5 * time.Second):
fmt.Println("timeout")
}
Functions
| Pattern | Description | Example |
|---|---|---|
| Basic function | Simple function with typed params | func add(a, b int) int { return a + b } |
| Multiple returns | Return more than one value | func divide(a, b float64) (float64, error) |
| Named returns | Name return values, use naked return | func calc(x int) (result int, err error) |
| Variadic function | Accept any number of arguments | func sum(nums ...int) int |
| Spread operator | Pass slice as variadic args | sum(numbers...) |
| Function value | Functions are first-class values | fn := func(x int) int { return x * 2 } |
| Closure | Function that captures surrounding variables | func counter() func() int { ... } |
init() |
Package initializer (runs before main) | func init() { ... } |
| Function type | Define a function signature as a type | type Handler func(string) error |
// Multiple return values (idiomatic Go error handling)
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, fmt.Errorf("division by zero")
}
return a / b, nil
}
// Variadic function
func sum(nums ...int) int {
total := 0
for _, n := range nums {
total += n
}
return total
}
// Closure
func counter() func() int {
count := 0
return func() int {
count++
return count
}
}
next := counter()
fmt.Println(next()) // 1
fmt.Println(next()) // 2
Arrays & Slices
| Operation | Description | Example |
|---|---|---|
| Array (fixed size) | Fixed-length, value type | var a [5]int |
| Array literal | Initialize with values | a := [3]string{"a", "b", "c"} |
Array with ... |
Let compiler count elements | a := [...]int{1, 2, 3, 4} |
| Slice (dynamic) | Dynamic-length reference to underlying array | s := []int{1, 2, 3} |
make() |
Create slice with length and capacity | s := make([]int, 5, 10) |
append() |
Add elements (may reallocate) | s = append(s, 4, 5, 6) |
| Append slice | Append one slice to another | s = append(s, other...) |
len() / cap() |
Length and capacity of slice | fmt.Println(len(s), cap(s)) |
| Slice expression | Create sub-slice [low:high] | sub := s[1:4] |
| Full slice expr | Control capacity [low:high:max] | sub := s[1:4:5] |
copy() |
Copy elements between slices | n := copy(dst, src) |
| Delete element | Remove element at index i | s = append(s[:i], s[i+1:]...) |
| Nil slice | Uninitialized slice (length 0, nil) | var s []int // s == nil |
// Slices in action
nums := []int{10, 20, 30, 40, 50}
// Slicing: [inclusive:exclusive]
first3 := nums[:3] // [10, 20, 30]
last2 := nums[3:] // [40, 50]
middle := nums[1:4] // [20, 30, 40]
// Append grows the slice
nums = append(nums, 60, 70)
// Iterate with index and value
for i, v := range nums {
fmt.Printf("nums[%d] = %d\n", i, v)
}
// 2D slice
matrix := [][]int{
{1, 2, 3},
{4, 5, 6},
}
Maps
| Operation | Description | Example |
|---|---|---|
| Create with literal | Initialize map with values | m := map[string]int{"a": 1, "b": 2} |
Create with make |
Create empty map | m := make(map[string]int) |
| Set value | Add or update key | m["key"] = 42 |
| Get value | Retrieve by key (zero value if missing) | v := m["key"] |
| Check existence | Comma-ok idiom | v, ok := m["key"] |
| Delete key | Remove entry (no-op if key absent) | delete(m, "key") |
| Iterate | Loop over all key-value pairs | for k, v := range m { ... } |
| Length | Number of entries | n := len(m) |
| Nil map | Read returns zero value; write panics | var m map[string]int // m == nil |
users := map[string]int{
"alice": 32,
"bob": 28,
}
// Check if key exists
if age, ok := users["alice"]; ok {
fmt.Printf("Alice is %d\n", age)
}
// Delete a key
delete(users, "bob")
// Map of slices
graph := map[string][]string{
"A": {"B", "C"},
"B": {"D"},
}
Tip: Map iteration order is randomized in Go. If you need sorted output, collect the keys into a slice, sort it, then iterate.
Structs & Methods
| Pattern | Description | Example |
|---|---|---|
| Define struct | Named collection of fields | type User struct { Name string; Age int } |
| Create instance | Initialize by field name | u := User{Name: "Alice", Age: 30} |
| Pointer to struct | Allocate on heap with & | u := &User{Name: "Bob"} |
| Access fields | Dot notation (auto-dereferences pointers) | fmt.Println(u.Name) |
| Struct tags | Metadata for encoding/reflection | Name string `json:"name" validate:"required"` |
| Embedding | Composition (promotes fields/methods) | type Admin struct { User; Role string } |
| Value receiver | Method on copy of struct | func (u User) Greet() string |
| Pointer receiver | Method can modify the struct | func (u *User) SetAge(age int) |
| Anonymous struct | Inline struct without a type name | p := struct{ X, Y int }{10, 20} |
| Constructor pattern | Factory function (Go has no constructors) | func NewUser(name string) *User |
type User struct {
Name string `json:"name"`
Email string `json:"email"`
Age int `json:"age,omitempty"`
}
// Value receiver — doesn't modify the original
func (u User) Greet() string {
return "Hi, I'm " + u.Name
}
// Pointer receiver — can modify the struct
func (u *User) SetAge(age int) {
u.Age = age
}
// Embedding for composition
type Admin struct {
User // embedded — Admin inherits User's fields and methods
Permissions []string
}
admin := Admin{
User: User{Name: "Alice", Email: "alice@dev.io"},
Permissions: []string{"read", "write"},
}
fmt.Println(admin.Name) // "Alice" — promoted from User
Interfaces
| Concept | Description | Example |
|---|---|---|
| Define interface | Set of method signatures | type Stringer interface { String() string } |
| Implicit implementation | No "implements" keyword needed | // Type satisfies interface if it has all methods |
| Empty interface | Accepts any type (like any) |
func Print(v interface{}) { ... } |
any |
Alias for interface{} (Go 1.18+) |
func Print(v any) { ... } |
| Type assertion | Extract concrete type from interface | s := i.(string) |
| Safe type assertion | Assertion with ok check | s, ok := i.(string) |
| Type switch | Branch on underlying type | switch v := i.(type) { case int: ... } |
| Interface embedding | Compose interfaces | type ReadWriter interface { Reader; Writer } |
| Stringer | Implement String() for custom printing |
func (u User) String() string { ... } |
type Shape interface {
Area() float64
Perimeter() float64
}
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 }
// Circle implicitly satisfies Shape
var s Shape = Circle{Radius: 5}
fmt.Println(s.Area()) // 78.5398...
// Type assertion
if c, ok := s.(Circle); ok {
fmt.Println("Radius:", c.Radius)
}
// Type switch
func describe(i interface{}) string {
switch v := i.(type) {
case int: return fmt.Sprintf("int: %d", v)
case string: return fmt.Sprintf("string: %s", v)
default: return "unknown"
}
}
Tip: Keep interfaces small. The Go standard library's io.Reader has just one method:
Read(p []byte) (n int, err error). Small interfaces are easier to implement and compose.Pointers
| Operation | Description | Example |
|---|---|---|
| Declare pointer | Pointer to a type | var p *int |
Address-of & |
Get memory address of variable | p := &x |
Dereference * |
Access value at pointer address | fmt.Println(*p) |
new() |
Allocate zero-valued memory, return pointer | p := new(int) // *p == 0 |
| Nil pointer | Uninitialized pointer is nil | var p *int // p == nil |
| Pointer to struct | Auto-dereferenced with dot notation | p := &User{Name: "Go"} |
| No pointer arithmetic | Go does not support pointer math (use unsafe if needed) | // p++ is not allowed |
func increment(p *int) {
*p++ // modify the original value
}
x := 10
increment(&x)
fmt.Println(x) // 11
// Pointer to struct
type Config struct { Debug bool }
cfg := &Config{Debug: true}
cfg.Debug = false // auto-dereferenced
Goroutines & Channels
| Concept | Description | Example |
|---|---|---|
| Goroutine | Lightweight concurrent function | go doWork() |
| Goroutine with closure | Launch anonymous function concurrently | go func() { ... }() |
| Unbuffered channel | Synchronous send/receive | ch := make(chan int) |
| Buffered channel | Async up to buffer size | ch := make(chan int, 10) |
| Send to channel | Blocks if unbuffered/full | ch <- 42 |
| Receive from channel | Blocks if empty | val := <-ch |
| Directional channel | Restrict to send-only or receive-only | func send(ch chan<- int) { ch <- 1 } |
| Close channel | Signal no more values will be sent | close(ch) |
| Range over channel | Receive until channel is closed | for v := range ch { ... } |
select |
Multiplex channel operations | select { case v := <-ch1: ... case ch2 <- x: ... } |
sync.WaitGroup |
Wait for a group of goroutines to finish | var wg sync.WaitGroup |
sync.Mutex |
Mutual exclusion lock | var mu sync.Mutex |
sync.Once |
Execute function exactly once | once.Do(func() { ... }) |
context.Context |
Cancellation, deadlines, values for goroutines | ctx, cancel := context.WithTimeout(...) |
// Worker pool with goroutines and channels
func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
fmt.Printf("worker %d processing job %d\n", id, j)
time.Sleep(time.Second)
results <- j * 2
}
}
func main() {
jobs := make(chan int, 100)
results := make(chan int, 100)
// Start 3 workers
for w := 1; w <= 3; w++ {
go worker(w, jobs, results)
}
// Send 5 jobs
for j := 1; j <= 5; j++ {
jobs <- j
}
close(jobs)
// Collect results
for r := 1; r <= 5; r++ {
fmt.Println(<-results)
}
}
// WaitGroup pattern
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
fmt.Printf("goroutine %d\n", id)
}(i)
}
wg.Wait() // blocks until all goroutines finish
Tip: Always pass loop variables as function arguments to goroutine closures to avoid data races. Use
go vet and the race detector (go run -race) to catch concurrency bugs.Error Handling
| Pattern | Description | Example |
|---|---|---|
error interface |
Built-in interface: Error() string |
func open(f string) (*File, error) |
| Check errors | Always check returned errors | if err != nil { return err } |
errors.New() |
Create simple error | err := errors.New("not found") |
fmt.Errorf() |
Formatted error string | err := fmt.Errorf("user %d: %w", id, err) |
Error wrapping %w |
Wrap errors for context chain | fmt.Errorf("open: %w", err) |
errors.Is() |
Check error chain for specific value | if errors.Is(err, os.ErrNotExist) { ... } |
errors.As() |
Check error chain for specific type | var pathErr *os.PathError |
| Custom error type | Struct implementing error interface | type NotFoundError struct { ID int } |
panic() |
Unrecoverable error (crashes program) | panic("fatal: out of memory") |
recover() |
Catch panic in deferred function | defer func() { if r := recover(); r != nil { ... } }() |
// Custom error type
type ValidationError struct {
Field string
Message string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("%s: %s", e.Field, e.Message)
}
// Wrapping errors for context
func readConfig(path string) ([]byte, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("readConfig %s: %w", path, err)
}
return data, nil
}
// Checking wrapped errors
_, err := readConfig("/etc/app.conf")
if errors.Is(err, os.ErrNotExist) {
fmt.Println("Config file missing — using defaults")
}
// Recover from panic
func safeDiv(a, b int) (result int, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic: %v", r)
}
}()
return a / b, nil
}
Packages & Imports
| Pattern | Description | Example |
|---|---|---|
| Package declaration | First line of every Go file | package main |
| Single import | Import one package | import "fmt" |
| Grouped import | Import multiple packages | import ( |
| Alias import | Rename a package locally | import f "fmt" |
| Blank import | Import for side effects only | import _ "image/png" |
| Dot import | Import into current namespace (avoid) | import . "math" |
| Exported names | Capitalized = public, lowercase = private | func DoWork() { ... } // exported |
| Internal packages | Only importable by parent tree | myapp/internal/db |
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"time"
"github.com/gorilla/mux" // third-party package
)
func main() {
r := mux.NewRouter()
// ...
}
String Manipulation
| Function | Description | Example |
|---|---|---|
strings.Contains(s, sub) |
Check if substring exists | strings.Contains("hello", "ell") // true |
strings.HasPrefix(s, p) |
Check if string starts with prefix | strings.HasPrefix("hello", "he") // true |
strings.HasSuffix(s, p) |
Check if string ends with suffix | strings.HasSuffix("hello", "lo") // true |
strings.Index(s, sub) |
Find first index of substring (-1 if not found) | strings.Index("hello", "ll") // 2 |
strings.Replace(s, old, new, n) |
Replace first n occurrences (-1 for all) | strings.Replace("foo", "o", "0", -1) // "f00" |
strings.ReplaceAll(s, old, new) |
Replace all occurrences | strings.ReplaceAll("aabb", "a", "x") // "xxbb" |
strings.Split(s, sep) |
Split string into slice | strings.Split("a,b,c", ",") // ["a","b","c"] |
strings.Join(s, sep) |
Join slice into string | strings.Join([]string{"a","b"}, "-") // "a-b" |
strings.ToUpper(s) |
Convert to uppercase | strings.ToUpper("hello") // "HELLO" |
strings.ToLower(s) |
Convert to lowercase | strings.ToLower("HELLO") // "hello" |
strings.TrimSpace(s) |
Remove leading/trailing whitespace | strings.TrimSpace(" hi ") // "hi" |
strings.Trim(s, cutset) |
Remove specified leading/trailing chars | strings.Trim("##hi##", "#") // "hi" |
strings.Repeat(s, n) |
Repeat string n times | strings.Repeat("ab", 3) // "ababab" |
strings.Count(s, sub) |
Count non-overlapping occurrences | strings.Count("hello", "l") // 2 |
strings.NewReader(s) |
Create io.Reader from string | r := strings.NewReader("data") |
strconv.Itoa(n) |
Int to string | strconv.Itoa(42) // "42" |
strconv.Atoi(s) |
String to int | n, err := strconv.Atoi("42") |
fmt.Sprintf() |
Format string (like printf) | s := fmt.Sprintf("name=%s age=%d", n, a) |
import ("fmt"; "strings"; "strconv")
// String builder for efficient concatenation
var b strings.Builder
for i := 0; i < 100; i++ {
fmt.Fprintf(&b, "item %d, ", i)
}
result := b.String()
// Multiline raw string literal
query := `SELECT id, name
FROM users
WHERE active = true
ORDER BY name`
// Rune iteration (for Unicode correctness)
for i, r := range "Hello, 世界" {
fmt.Printf("byte %d: %c (U+%04X)\n", i, r, r)
}
File I/O
| Operation | Description | Example |
|---|---|---|
os.ReadFile(path) |
Read entire file into []byte | data, err := os.ReadFile("f.txt") |
os.WriteFile(path, data, perm) |
Write []byte to file | os.WriteFile("f.txt", data, 0644) |
os.Open(path) |
Open file for reading | f, err := os.Open("f.txt") |
os.Create(path) |
Create or truncate file for writing | f, err := os.Create("f.txt") |
os.OpenFile(path, flag, perm) |
Open with specific flags (append, etc.) | os.OpenFile("f.txt", os.O_APPEND|os.O_WRONLY, 0644) |
f.Close() |
Close file (always defer this) | defer f.Close() |
bufio.Scanner |
Read file line by line | scanner := bufio.NewScanner(f) |
bufio.Writer |
Buffered writes | w := bufio.NewWriter(f) |
io.Copy(dst, src) |
Copy from Reader to Writer | io.Copy(os.Stdout, resp.Body) |
os.Mkdir(path, perm) |
Create directory | os.Mkdir("data", 0755) |
os.MkdirAll(path, perm) |
Create directory tree | os.MkdirAll("a/b/c", 0755) |
os.Remove(path) |
Delete file or empty directory | os.Remove("f.txt") |
os.Stat(path) |
Get file info (size, mode, modtime) | info, err := os.Stat("f.txt") |
filepath.Walk() |
Recursively walk directory tree | filepath.Walk(".", walkFn) |
// Read file line by line
f, err := os.Open("data.txt")
if err != nil { log.Fatal(err) }
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Text()
fmt.Println(line)
}
// Write JSON to file
type Config struct {
Host string `json:"host"`
Port int `json:"port"`
}
cfg := Config{Host: "localhost", Port: 8080}
data, _ := json.MarshalIndent(cfg, "", " ")
os.WriteFile("config.json", data, 0644)
Common Standard Library
fmt - Formatted I/O
| Function | Description | Example |
|---|---|---|
fmt.Println() |
Print with newline | fmt.Println("hello", 42) |
fmt.Printf() |
Formatted print (%s %d %v %T %+v) |
fmt.Printf("name=%s age=%d\n", n, a) |
fmt.Sprintf() |
Return formatted string | s := fmt.Sprintf("%d items", count) |
fmt.Fprintf() |
Write formatted to io.Writer | fmt.Fprintf(os.Stderr, "error: %v\n", err) |
fmt.Errorf() |
Return formatted error | fmt.Errorf("failed: %w", err) |
fmt Verbs (Format Specifiers)
| Verb | Description | Example Output |
|---|---|---|
%v | Default format | {Alice 30} |
%+v | With field names | {Name:Alice Age:30} |
%#v | Go syntax representation | main.User{Name:"Alice", Age:30} |
%T | Type of value | main.User |
%d | Integer (decimal) | 42 |
%x / %o / %b | Hex / octal / binary | 2a / 52 / 101010 |
%f | Float (default precision) | 3.141593 |
%.2f | Float with 2 decimal places | 3.14 |
%s | String | hello |
%q | Quoted string | "hello" |
%p | Pointer address | 0xc0000b2000 |
%w | Wrap error (Errorf only) | - |
net/http - HTTP Server & Client
// Simple HTTP server
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:])
}
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(":8080", nil))
// HTTP GET request
resp, err := http.Get("https://api.example.com/data")
if err != nil { log.Fatal(err) }
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
// HTTP POST with JSON
payload := strings.NewReader(`{"name":"Go"}`)
resp, err := http.Post("https://api.example.com/users", "application/json", payload)
// Custom HTTP client with timeout
client := &http.Client{Timeout: 10 * time.Second}
resp, err := client.Get("https://api.example.com")
encoding/json - JSON Encoding/Decoding
type User struct {
Name string `json:"name"`
Email string `json:"email"`
Age int `json:"age,omitempty"` // omit if zero
Pass string `json:"-"` // always omit
Tags []string `json:"tags"`
}
// Marshal (struct to JSON)
u := User{Name: "Alice", Email: "a@b.com"}
jsonBytes, err := json.Marshal(u)
jsonPretty, _ := json.MarshalIndent(u, "", " ")
// Unmarshal (JSON to struct)
var user User
err := json.Unmarshal(jsonBytes, &user)
// Decode from io.Reader (e.g., HTTP response body)
var user User
err := json.NewDecoder(resp.Body).Decode(&user)
// Encode to io.Writer
err := json.NewEncoder(os.Stdout).Encode(user)
// Dynamic JSON with map
var data map[string]interface{}
json.Unmarshal(jsonBytes, &data)
time - Time & Duration
// Current time
now := time.Now()
fmt.Println(now.Year(), now.Month(), now.Day())
// Format (uses reference time: Mon Jan 2 15:04:05 MST 2006)
s := now.Format("2006-01-02 15:04:05")
s = now.Format(time.RFC3339) // "2024-03-15T10:30:00Z"
// Parse a time string
t, err := time.Parse("2006-01-02", "2024-12-25")
// Duration
d := 5 * time.Second
time.Sleep(100 * time.Millisecond)
// Timer and Ticker
timer := time.NewTimer(2 * time.Second)
<-timer.C // blocks for 2s
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for t := range ticker.C {
fmt.Println("tick at", t)
}
// Measure elapsed time
start := time.Now()
doWork()
elapsed := time.Since(start)
fmt.Printf("Took %s\n", elapsed)
Tip: Go uses the reference time
Mon Jan 2 15:04:05 MST 2006 (01/02 03:04:05 '06 -0700) for formatting. This is a mnemonic: 1-2-3-4-5-6-7. Unlike most languages, you don't use YYYY-MM-DD.os - Operating System Interface
| Function | Description | Example |
|---|---|---|
os.Args |
Command-line arguments | args := os.Args[1:] |
os.Getenv(key) |
Get environment variable | home := os.Getenv("HOME") |
os.Setenv(key, val) |
Set environment variable | os.Setenv("PORT", "8080") |
os.Exit(code) |
Exit with status code | os.Exit(1) |
os.Getwd() |
Get working directory | dir, _ := os.Getwd() |
os.Stdin/Stdout/Stderr |
Standard I/O file descriptors | fmt.Fprintln(os.Stderr, "error") |
Go Modules
| Command | Description | Example |
|---|---|---|
go mod init |
Initialize a new module (creates go.mod) | go mod init github.com/user/project |
go get |
Add/update dependency | go get github.com/gorilla/mux@latest |
go mod tidy |
Add missing, remove unused dependencies | go mod tidy |
go mod download |
Download dependencies to local cache | go mod download |
go mod vendor |
Copy deps into vendor/ directory | go mod vendor |
go.mod |
Module definition file | module github.com/user/project |
go.sum |
Cryptographic checksums for dependencies | // Auto-generated, commit to version control |
go build |
Compile packages and dependencies | go build -o myapp ./cmd/server |
go run |
Compile and run | go run main.go |
go test |
Run tests | go test ./... -v -race |
go fmt |
Format source code | go fmt ./... |
go vet |
Report likely bugs | go vet ./... |
go install |
Compile and install binary to $GOPATH/bin | go install github.com/user/tool@latest |
| Cross-compile | Build for different OS/arch | GOOS=linux GOARCH=amd64 go build |
# Initialize a new project
mkdir myapp && cd myapp
go mod init github.com/username/myapp
# Add a dependency
go get github.com/gin-gonic/gin@latest
# Run tests with race detector and coverage
go test ./... -race -coverprofile=coverage.out
go tool cover -html=coverage.out
# Build for multiple platforms
GOOS=linux GOARCH=amd64 go build -o myapp-linux
GOOS=darwin GOARCH=arm64 go build -o myapp-mac
GOOS=windows GOARCH=amd64 go build -o myapp.exe
# Common project layout
myapp/
cmd/
server/main.go # entry points
internal/ # private packages
handler/
service/
pkg/ # public packages
go.mod
go.sum