Go Developer Guide
Section titled “Go Developer Guide”Setting Up Go
Section titled “Setting Up Go”Install & Verify
Section titled “Install & Verify”# Download from https://golang.org/dl/go version # Check installed Go versiongo env # Show all Go environment variablesgo env GOPATH # Show GOPATH directorygo env GOROOT # Show Go installation directoryInitialize a Project
Section titled “Initialize a Project”go mod init <module_name> # Initialize a new module (e.g. go mod init myapp)go mod tidy # Add missing and remove unused dependenciesgo mod download # Download all dependencies to local cachego mod vendor # Copy dependencies into ./vendor directoryRunning & Building
Section titled “Running & Building”go run main.go # Compile and run a Go file directlygo run . # Run the package in current directorygo build # Compile binary into current directorygo build -o myapp # Compile with custom output namego build ./... # Build all packages in modulego install # Compile and install to $GOPATH/bingo clean # Remove compiled object filesBasic Syntax
Section titled “Basic Syntax”Hello World
Section titled “Hello World”package main
import "fmt"
func main() { fmt.Println("Hello, World!")}Variables & Constants
Section titled “Variables & Constants”// Variable declarationvar name string = "Go" // Explicit type declarationvar age int // Zero value: 0message := "Hello" // Short declaration (inside functions only)
// Multiple variablesvar x, y int = 10, 20a, b := true, 3.14
// Constantsconst Pi = 3.14159const ( StatusOK = 200 StatusError = 500)Data Types
Section titled “Data Types”// Basic typesbool // true / falsestring // "text" (UTF-8)int int8 int16 int32 int64 // Signed integersuint uint8 uint16 uint32 uint64 // Unsigned integersfloat32 float64 // Floating pointcomplex64 complex128 // Complex numbersbyte // Alias for uint8rune // Alias for int32 (Unicode code point)
// Type conversion (explicit only — no implicit casting)i := 42f := float64(i)u := uint(f)s := string(rune(65)) // "A"Control Flow
Section titled “Control Flow”If / Else
Section titled “If / Else”if x > 10 { fmt.Println("big")} else if x > 5 { fmt.Println("medium")} else { fmt.Println("small")}
// If with init statementif val, err := strconv.Atoi("42"); err == nil { fmt.Println(val)}Switch
Section titled “Switch”switch day {case "Mon", "Tue", "Wed", "Thu", "Fri": fmt.Println("Weekday")case "Sat", "Sun": fmt.Println("Weekend")default: fmt.Println("Unknown")}
// Typeless switch (replaces long if-else)switch {case age < 18: fmt.Println("Minor")case age >= 18: fmt.Println("Adult")}// For (Go's only loop keyword)for i := 0; i < 5; i++ { fmt.Println(i)}
// While-stylefor x < 100 { x *= 2}
// Infinite loopfor { // break to exit}
// Range over slice/arrayfor i, v := range nums { fmt.Println(i, v)}
// Range over mapfor k, v := range myMap { fmt.Println(k, v)}
// Range over string (yields runes)for i, ch := range "hello" { fmt.Printf("%d: %c\n", i, ch)}Functions
Section titled “Functions”Basic Functions
Section titled “Basic Functions”func add(a, b int) int { return a + b}
// Multiple return valuesfunc divide(a, b float64) (float64, error) { if b == 0 { return 0, errors.New("division by zero") } return a / b, nil}
// Named return valuesfunc minMax(nums []int) (min, max int) { min, max = nums[0], nums[0] for _, v := range nums { if v < min { min = v } if v > max { max = v } } return // Naked return}
// Variadic functionfunc sum(nums ...int) int { total := 0 for _, n := range nums { total += n } return total}sum(1, 2, 3) // Pass individual argssum(nums...) // Spread a sliceFirst-Class Functions
Section titled “First-Class Functions”// Function as variabledouble := func(n int) int { return n * 2 }fmt.Println(double(5)) // 10
// Function as argumentapply := func(f func(int) int, x int) int { return f(x) }
// Immediately invoked functionresult := func(x int) int { return x * x }(9)
// Closurefunc counter() func() int { count := 0 return func() int { count++ return count }}c := counter()c() // 1c() // 2Defer, Panic, Recover
Section titled “Defer, Panic, Recover”// Defer: runs when surrounding function returns (LIFO order)defer fmt.Println("cleanup")
// Panic: stops normal executionpanic("something went wrong")
// Recover: catches a panic (must be inside defer)defer func() { if r := recover(); r != nil { fmt.Println("Recovered:", r) }}()Arrays, Slices & Maps
Section titled “Arrays, Slices & Maps”Arrays
Section titled “Arrays”var arr [3]int // [0, 0, 0]arr := [3]int{1, 2, 3}arr := [...]int{4, 5, 6} // Compiler infers lengtharr[0] = 10len(arr) // 3Slices
Section titled “Slices”s := []int{1, 2, 3} // Slice literals := make([]int, 5) // Length 5, capacity 5s := make([]int, 3, 10) // Length 3, capacity 10
s = append(s, 4) // Append single elements = append(s, 5, 6, 7) // Append multiples = append(s, other...) // Append another slice
s[1:3] // Slice of index 1 to 2 (not 3)s[:3] // From start to index 2s[2:] // From index 2 to endcopy(dst, src) // Copy elements from src to dst
len(s) // Number of elementscap(s) // Underlying array capacitym := map[string]int{"a": 1, "b": 2}m := make(map[string]int)
m["key"] = 42 // Set valuev := m["key"] // Get value (zero if missing)v, ok := m["key"] // ok is false if key absentdelete(m, "key") // Remove key
// Iteratefor k, v := range m { fmt.Println(k, v)}Structs
Section titled “Structs”Definition & Usage
Section titled “Definition & Usage”type Person struct { Name string Age int}
p := Person{Name: "Alice", Age: 30} // Named fieldsp := Person{"Alice", 30} // Positional (fragile, avoid)p.Name = "Bob" // Field accesspp := &Person{Name: "Carol"} // Pointer to struct
// Anonymous structconfig := struct { Host string Port int}{"localhost", 8080}Methods
Section titled “Methods”// Value receiver (copy)func (p Person) Greet() string { return "Hi, I'm " + p.Name}
// Pointer receiver (modifies original)func (p *Person) Birthday() { p.Age++}
p.Birthday() // Auto-dereferenced(&p).Birthday() // EquivalentEmbedding (Composition)
Section titled “Embedding (Composition)”type Animal struct { Name string}func (a Animal) Speak() string { return a.Name + " speaks" }
type Dog struct { Animal // Embedded — promotes fields/methods Breed string}
d := Dog{Animal: Animal{Name: "Rex"}, Breed: "Lab"}d.Speak() // Promoted from Animald.Name // Promoted fieldInterfaces
Section titled “Interfaces”Definition & Implementation
Section titled “Definition & Implementation”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) }
// Implicit satisfaction — no "implements" keywordvar s Shape = Rectangle{5, 3}s.Area() // 15Empty Interface & Type Assertions
Section titled “Empty Interface & Type Assertions”var i interface{} = "hello" // any type (use `any` in Go 1.18+)var a any = 42
// Type assertions := i.(string) // Panics if wrong types, ok := i.(string) // Safe form
// Type switchswitch v := i.(type) {case int: fmt.Println("int:", v)case string: fmt.Println("string:", v)default: fmt.Println("other")}Pointers
Section titled “Pointers”x := 42p := &x // & = address of x*p = 100 // * = dereference (modifies x)fmt.Println(x) // 100
// new() allocates zeroed memory, returns pointerp := new(int)*p = 7
// Pointers with structstype Node struct{ Val int }n := &Node{Val: 1}n.Val = 2 // Auto-dereferenced (no n->Val like C)Error Handling
Section titled “Error Handling”// Idiomatic: return error as last valuefunc readFile(path string) ([]byte, error) { data, err := os.ReadFile(path) if err != nil { return nil, fmt.Errorf("readFile: %w", err) // Wrap error } return data, nil}
// Check and handledata, err := readFile("config.json")if err != nil { log.Fatal(err)}
// Custom error typestype ValidationError struct { Field string Message string}func (e *ValidationError) Error() string { return fmt.Sprintf("%s: %s", e.Field, e.Message)}
// Unwrap errors (Go 1.13+)errors.Is(err, os.ErrNotExist) // Check error chainerrors.As(err, &myErr) // Extract concrete type from chainGoroutines & Concurrency
Section titled “Goroutines & Concurrency”Goroutines
Section titled “Goroutines”go func() { fmt.Println("runs concurrently")}()
go doWork(arg) // Launch any function as goroutine
// Wait for goroutines with WaitGroupvar wg sync.WaitGroupfor i := 0; i < 5; i++ { wg.Add(1) go func(id int) { defer wg.Done() fmt.Println("worker", id) }(i)}wg.Wait() // Block until all Done()Channels
Section titled “Channels”ch := make(chan int) // Unbuffered channelch := make(chan int, 10) // Buffered channel (capacity 10)
ch <- 42 // Send (blocks if unbuffered/full)v := <-ch // Receive (blocks until data)v, ok := <-ch // ok is false if channel closedclose(ch) // Signal no more sends
// Range over channelfor v := range ch { // Exits when channel closed fmt.Println(v)}
// Directional channels (for function params)func producer(out chan<- int) { out <- 1 } // Send-onlyfunc consumer(in <-chan int) { fmt.Println(<-in) } // Receive-onlySelect
Section titled “Select”select {case msg := <-ch1: fmt.Println("ch1:", msg)case msg := <-ch2: fmt.Println("ch2:", msg)case ch3 <- "hello": fmt.Println("sent to ch3")default: fmt.Println("no channel ready") // Non-blocking}Mutex & Sync Primitives
Section titled “Mutex & Sync Primitives”var mu sync.Mutexmu.Lock()// critical sectionmu.Unlock()
// RWMutex: multiple readers, one writervar rw sync.RWMutexrw.RLock() / rw.RUnlock() // Shared read lockrw.Lock() / rw.Unlock() // Exclusive write lock
// Once: run exactly oncevar once sync.Onceonce.Do(func() { fmt.Println("only once") })
// Atomic operationsvar counter int64atomic.AddInt64(&counter, 1)atomic.LoadInt64(&counter)Generics (Go 1.18+)
Section titled “Generics (Go 1.18+)”// Generic functionfunc Map[T, U any](s []T, f func(T) U) []U { result := make([]U, len(s)) for i, v := range s { result[i] = f(v) } return result}
// Type constraintstype Number interface { int | int64 | float64}
func Sum[T Number](nums []T) T { var total T for _, n := range nums { total += n } return total}
// Generic structtype Stack[T any] struct { items []T}func (s *Stack[T]) Push(v T) { s.items = append(s.items, v) }func (s *Stack[T]) Pop() T { n := len(s.items) - 1 v := s.items[n] s.items = s.items[:n] return v}Packages & Modules
Section titled “Packages & Modules”go get github.com/pkg/errors # Add a dependencygo get github.com/pkg/errors@v1.9.1 # Specific versiongo get github.com/pkg/errors@latest # Latest versiongo list -m all # List all module dependenciesgo mod graph # Show dependency graphgo mod why github.com/pkg/errors # Explain why dep is needed// Import stylesimport "fmt" // Standard libraryimport "github.com/pkg/errors" // Third-partyimport ( // Grouped imports "fmt" "os" "github.com/pkg/errors")import _ "image/png" // Blank import (side effects only)import f "fmt" // Aliased importFile I/O
Section titled “File I/O”// Read entire filedata, err := os.ReadFile("file.txt")
// Write entire fileerr := os.WriteFile("file.txt", []byte("hello"), 0644)
// Open / closef, err := os.Open("file.txt") // Read-onlydefer f.Close()
f, err := os.Create("file.txt") // Write (truncates)f, err := os.OpenFile("file.txt", os.O_APPEND|os.O_WRONLY, 0644)
// Buffered readerscanner := bufio.NewScanner(f)for scanner.Scan() { fmt.Println(scanner.Text()) // Line by line}
// Buffered writerw := bufio.NewWriter(f)fmt.Fprintln(w, "line")w.Flush() // Don't forget to flush!Testing
Section titled “Testing”go test ./... # Run all tests in modulego test -v ./... # Verbose outputgo test -run TestFuncName # Run specific testgo test -bench=. # Run benchmarksgo test -cover # Show coverage summarygo test -coverprofile=cov.out # Write coverage profilego tool cover -html=cov.out # Open coverage in browsergo test -race ./... # Run with race detector// Basic test (file must end in _test.go)func TestAdd(t *testing.T) { got := add(2, 3) if got != 5 { t.Errorf("add(2,3) = %d; want 5", got) }}
// Table-driven testsfunc TestMultiply(t *testing.T) { tests := []struct { a, b, want int }{ {2, 3, 6}, {0, 5, 0}, {-1, 4, -4}, } for _, tc := range tests { got := multiply(tc.a, tc.b) if got != tc.want { t.Errorf("multiply(%d,%d) = %d; want %d", tc.a, tc.b, got, tc.want) } }}
// Benchmarkfunc BenchmarkAdd(b *testing.B) { for i := 0; i < b.N; i++ { add(1, 2) }}
// Subtestsfunc TestGroup(t *testing.T) { t.Run("case A", func(t *testing.T) { /* ... */ }) t.Run("case B", func(t *testing.T) { /* ... */ })}Common Standard Library Packages
Section titled “Common Standard Library Packages”fmt.Println("hello", x) # Print with newlinefmt.Printf("name: %s, age: %d\n", n, a) # Formatted printfmt.Sprintf("val: %v", x) # Format to stringfmt.Fprintf(w, "to writer: %s", s) # Format to io.Writerfmt.Errorf("wrap: %w", err) # Create formatted error// Verbs: %v (default), %T (type), %d (int), %f (float), %s (string), %q (quoted), %p (pointer)strings
Section titled “strings”strings.Contains(s, "sub") # true/falsestrings.HasPrefix(s, "pre") # true/falsestrings.HasSuffix(s, "suf") # true/falsestrings.ToUpper(s) / strings.ToLower(s)strings.TrimSpace(s) # Remove leading/trailing whitespacestrings.Trim(s, "!?") # Remove specific chars from both endsstrings.Split(s, ",") # []stringstrings.Join(parts, "-") # stringstrings.Replace(s, "old", "new", n) # n=-1 replaces allstrings.Count(s, "sub") # Occurrencesstrings.Index(s, "sub") # First index, -1 if not foundstrings.TrimPrefix(s, "prefix")strings.Fields(s) # Split on any whitespacestrconv
Section titled “strconv”strconv.Atoi("42") # string → int (returns int, error)strconv.Itoa(42) # int → stringstrconv.ParseFloat("3.14", 64) # string → float64strconv.FormatFloat(3.14, 'f', 2, 64) # float64 → string "3.14"strconv.ParseBool("true") # string → boolstrconv.FormatBool(true) # bool → stringos & path
Section titled “os & path”os.Getenv("HOME") # Get environment variableos.Setenv("KEY", "val") # Set environment variableos.Args # []string of CLI argumentsos.Exit(1) # Exit with codeos.Mkdir("dir", 0755) # Create directoryos.MkdirAll("a/b/c", 0755) # Create nested directoriesos.Remove("file.txt") # Delete fileos.Rename("old", "new") # Move/renameos.Stat("file.txt") # Get file info (FileInfo, error)
filepath.Join("a", "b", "c") # "a/b/c" (OS-safe)filepath.Dir("/a/b/c") # "/a/b"filepath.Base("/a/b/c") # "c"filepath.Ext("file.txt") # ".txt"time.Now() # Current timetime.Now().Unix() # Unix timestamp (seconds)time.Sleep(2 * time.Second) # Sleep for durationtime.Second / time.Millisecond / time.Minute
t := time.Now()t.Format("2006-01-02 15:04:05") // Format (Go's reference time)time.Parse("2006-01-02", "2024-01-15") // Parse string to Time
since := time.Since(start) // Duration elapseduntil := time.Until(deadline) // Duration remaining
ticker := time.NewTicker(1 * time.Second)timer := time.NewTimer(5 * time.Second)Context
Section titled “Context”// Create contextsctx := context.Background() // Root context (never cancelled)ctx := context.TODO() // Placeholder context
// With cancellationctx, cancel := context.WithCancel(context.Background())defer cancel() // Always call cancel
// With timeoutctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)defer cancel()
// With deadlinedeadline := time.Now().Add(10 * time.Second)ctx, cancel := context.WithDeadline(context.Background(), deadline)defer cancel()
// With valuectx = context.WithValue(ctx, "userID", 42)val := ctx.Value("userID").(int)
// Check cancellation in goroutinesselect {case <-ctx.Done(): fmt.Println("cancelled:", ctx.Err()) // context.Canceled or DeadlineExceededdefault: // continue work}HTTP Server & Client
Section titled “HTTP Server & Client”HTTP Server
Section titled “HTTP Server”http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:])})http.ListenAndServe(":8080", nil)
// With custom muxmux := http.NewServeMux()mux.HandleFunc("/api/users", usersHandler)server := &http.Server{ Addr: ":8080", Handler: mux, ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second,}server.ListenAndServe()HTTP Client
Section titled “HTTP Client”// Simple GETresp, err := http.Get("https://api.example.com/data")defer resp.Body.Close()body, err := io.ReadAll(resp.Body)
// With timeoutclient := &http.Client{Timeout: 10 * time.Second}resp, err := client.Get("https://api.example.com")
// POST with JSONpayload, _ := json.Marshal(map[string]string{"key": "val"})resp, err := http.Post(url, "application/json", bytes.NewBuffer(payload))
// Custom request with headersreq, _ := http.NewRequestWithContext(ctx, "GET", url, nil)req.Header.Set("Authorization", "Bearer "+token)resp, err := client.Do(req)JSON Encoding & Decoding
Section titled “JSON Encoding & Decoding”type User struct { Name string `json:"name"` Email string `json:"email,omitempty"` // Omit if empty pass string // Unexported = ignored}
// Struct → JSONdata, err := json.Marshal(u)jsonStr := string(data)
// JSON → Structvar u Usererr := json.Unmarshal([]byte(jsonStr), &u)
// Stream encoding/decodingenc := json.NewEncoder(w) // w = io.Writer (e.g. ResponseWriter)enc.Encode(u)
dec := json.NewDecoder(r.Body) // r.Body = io.Readerdec.Decode(&u)
// Arbitrary JSONvar raw map[string]interface{}json.Unmarshal(data, &raw)Useful Go CLI Tools
Section titled “Useful Go CLI Tools”go fmt ./... # Format all Go source filesgo vet ./... # Report likely mistakes in codego doc fmt.Println # Show documentation for a symbolgo doc -all fmt # Show all docs for a packagegodoc -http=:6060 # Serve local documentationgo generate ./... # Run //go:generate directivesgopls # Official Go language server (LSP)staticcheck ./... # Advanced static analysis (install separately)dlv debug main.go # Debug with Delve debuggerGo Proverbs (Best Practices)
Section titled “Go Proverbs (Best Practices)”Don't communicate by sharing memory; share memory by communicating.Concurrency is not parallelism.Errors are values — handle them, don't ignore them.The bigger the interface, the weaker the abstraction.Accept interfaces, return structs.Make the zero value useful.A little copying is better than a little dependency.Clear is better than clever.