thecodex.expert · The Codex Family of Knowledge
Language Reference

Go

Simple, compiled, concurrent — built for the scale of Google, used for Docker, Kubernetes, and the modern cloud infrastructure stack.

Language Reference Go 1.26 · August 2024 Static typing Last verified:
New to Go? This is the reference encyclopedia — dip in anytime. To learn step by step, start the Go Course →
Canonical Definition

Go (Golang) is a statically typed, compiled, garbage-collected programming language designed at Google for simplicity, fast compilation, and built-in concurrency via goroutines and channels — used for cloud infrastructure, web services, and CLIs at scale.

📑 Go Reference — All Topics

Interfaces & Types

Structural typing, type assertions, type switches, embedding.

Goroutines & Channels

go keyword, channels, select, sync package.

Error Handling & Stdlib

error interface, wrapping, net/http, encoding/json.

What is Go

A language built to fix Google's own build-time and concurrency problems.

Setup and Tooling

One download: the compiler, stdlib, and go command in a single toolchain.

Variables and Types

Static types, zero values, and var vs := explained.

Control Flow

if, for, and switch — Go has only one loop keyword.

Functions and defer

Multiple return values, named returns, and guaranteed LIFO cleanup.

Structs and Methods

No classes: structs group data, methods bind functions to types.

Pointers

The useful half of C's pointers, without the dangerous half.

Slices and Arrays

Arrays are fixed; slices grow — and append() has real growth rules.

Maps

The comma-ok idiom, nil-map panics, and randomized iteration order.

Strings and Runes

Why indexing a string gives a byte, not a character.

select and sync

select multiplexes channels; sync.Mutex and WaitGroup handle the rest.

Context

Cancellation and deadlines that propagate through an entire call chain.

Generics

Type parameters, added in Go 1.18 — nine years after Go's first release.

Packages and Modules

No public/private keywords — capitalization is the whole visibility system.

Testing

No framework to install — name a function TestXxx and go test finds it.

Reflection

Inspect types and values at runtime — powerful, but a last resort.

Embedding

Looks like inheritance, works like composition — no dynamic dispatch.

JSON and Encoding

Struct tags control JSON keys; unexported fields are silently omitted.

IO and Files

Two one-method interfaces — Reader and Writer — unify all Go IO.

HTTP Servers

A production HTTP server in ~9 lines, no framework required.

Closures

Capture-by-reference, and the loop-variable bug Go 1.22 finally fixed.

Iterators and range

Go 1.23's range-over-func: custom, lazy iterators without a slice.

Memory and Garbage Collection

Escape analysis decides stack vs heap; the concurrent collector does the rest.

Build and Compile

One binary, any platform — GOOS and GOARCH, no extra toolchain.

Standard Library

A production HTTP server and JSON API with zero third-party dependencies.

Concurrency Patterns

Worker pools, pipelines, fan-out/fan-in — all built from goroutines and channels.

Modules and Dependencies

Semantic versioning, go.sum integrity, and the /v2 import-path rule.

One sentence

Go is the language Google built for the scale of the internet — compiled, statically typed, and fast, but with concurrency built into the language itself through goroutines and channels that make writing networked servers dramatically simpler.

What Go is

Go (also called Golang) is a statically typed, compiled, garbage-collected programming language designed at Google by Robert Griesemer, Rob Pike, and Ken Thompson, with version 1.0 released in March 2012. Go's design philosophy is radical simplicity: a small language specification, fast compilation, a powerful standard library, and first-class concurrency primitives (goroutines and channels). Go was designed to replace C++ and Java for large-scale server software at Google, where multi-million-line codebases and hundreds of engineers require fast builds and readable code.

Go is used for cloud infrastructure (Docker, Kubernetes, Terraform, Prometheus), web services, CLIs, and anywhere speed and concurrency matter. Its mascot is a gopher.

Gohello.go
package main   // every Go file belongs to a package

import (
    "fmt"
    "strings"
)

func main() {
    // Variables: explicit or inferred
    var name string = "Priya"
    age := 28                  // := short declaration, type inferred
    const pi = 3.14159

    fmt.Printf("Hello, %s! Age: %d\n", name, age)

    // Slices (dynamic arrays)
    fruits := []string{"mango", "apple", "banana"}
    fruits = append(fruits, "guava")
    fmt.Println(strings.Join(fruits, ", "))

    // Maps (hash tables)
    scores := map[string]int{
        "Priya": 95,
        "Rahul": 88,
    }
    scores["Anita"] = 72
    fmt.Println(scores["Priya"])
}

Types and interfaces

Go has structs for data and interfaces for behaviour. Go interfaces are implicit — a type satisfies an interface by implementing all its methods, without declaring that it does so. This is structural typing for interfaces: if a type has the right methods, it implements the interface. No implements keyword needed.

Gotypes.go
package main

import (
    "fmt"
    "math"
)

// Struct — data grouping
type Point struct {
    X, Y float64
}

// Method on struct — Go's version of OOP
func (p Point) Distance() float64 {
    return math.Sqrt(p.X*p.X + p.Y*p.Y)
}

// Interface — implicit implementation
type Shape interface {
    Area() float64
    Perimeter() float64
}

type Circle struct{ Radius float64 }
type Rect struct{ Width, Height float64 }

func (c Circle) Area() float64      { return math.Pi * c.Radius * c.Radius }
func (c Circle) Perimeter() float64 { return 2 * math.Pi * c.Radius }
func (r Rect) Area() float64        { return r.Width * r.Height }
func (r Rect) Perimeter() float64   { return 2 * (r.Width + r.Height) }

// Accepts any Shape — Circle and Rect both qualify
func printShape(s Shape) {
    fmt.Printf("Area: %.2f, Perimeter: %.2f\n", s.Area(), s.Perimeter())
}

func main() {
    printShape(Circle{Radius: 5})
    printShape(Rect{Width: 4, Height: 3})
}

Goroutines and channels

A goroutine is a lightweight, concurrently executing function. Starting one costs only a few kilobytes of stack space (versus ~1MB for an OS thread). The Go runtime multiplexes thousands of goroutines onto a pool of OS threads. Starting a goroutine: go functionName(). Goroutines communicate via channels — typed conduits that synchronise goroutines. The Go philosophy: Do not communicate by sharing memory; share memory by communicating.

Gogoroutines.go
package main

import (
    "fmt"
    "sync"
)

func worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) {
    defer wg.Done()
    for job := range jobs {
        result := job * job   // compute square
        results <- result
    }
}

func main() {
    jobs    := make(chan int, 10)
    results := make(chan int, 10)
    var wg sync.WaitGroup

    // Start 3 worker goroutines
    for w := 1; w <= 3; w++ {
        wg.Add(1)
        go worker(w, jobs, results, &wg)
    }

    // Send 9 jobs
    for j := 1; j <= 9; j++ {
        jobs <- j
    }
    close(jobs)

    // Wait for all workers, then close results
    go func() { wg.Wait(); close(results) }()

    // Collect results
    for r := range results {
        fmt.Println(r)
    }
}

Error handling

Go has no exceptions. Functions that can fail return an error as their last return value. Callers check the error explicitly. This makes error paths visible in the code and prevents errors from being silently swallowed. The convention: return nil for success, a non-nil error for failure.

Goerrors.go
package main

import (
    "errors"
    "fmt"
    "strconv"
)

func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("division by zero")
    }
    return a / b, nil
}

func parseAndDouble(s string) (int, error) {
    n, err := strconv.Atoi(s)
    if err != nil {
        return 0, fmt.Errorf("parseAndDouble: %w", err)  // wrap error
    }
    return n * 2, nil
}

func main() {
    result, err := divide(10, 0)
    if err != nil {
        fmt.Println("Error:", err)   // Error: division by zero
        return
    }
    fmt.Println(result)

    // errors.Is: check error chain
    _, err = parseAndDouble("not-a-number")
    var numErr *strconv.NumError
    if errors.As(err, &numErr) {
        fmt.Println("Got a NumError:", numErr.Num)
    }
}

Standard library and tooling

Go's standard library is exceptionally comprehensive: net/http (full HTTP server and client), encoding/json (JSON), database/sql (database interface), crypto/tls, testing (built-in test framework), sync (mutexes, wait groups), context (cancellation propagation), io and bufio (I/O), os and filepath. Go ships with: go fmt (canonical formatter — no debates), go test, go build, go mod (modules), go vet, and go doc.

The Go scheduler: M:N threading

Go uses an M:N scheduler (M goroutines on N OS threads). The scheduler has three entities: G (goroutine), M (machine = OS thread), and P (processor = scheduling context, capped at GOMAXPROCS). Each P has a local run queue of goroutines. The scheduler uses work stealing: when a P's local queue is empty, it steals goroutines from other Ps. Goroutines are preempted at function call sites (cooperative) and since Go 1.14, asynchronously (full preemption via signals). This means a tight CPU loop is preemptible — no goroutine can starve others.

select statement: multiplexing channels

The select statement is like a switch for channels — it blocks until one of its cases can proceed, then executes that case. If multiple cases are ready simultaneously, one is chosen uniformly at random. select with a default case is non-blocking.

Goselect.go
package main

import (
    "fmt"
    "time"
)

func main() {
    ch1 := make(chan string)
    ch2 := make(chan string)

    go func() { time.Sleep(1 * time.Second); ch1 <- "one" }()
    go func() { time.Sleep(2 * time.Second); ch2 <- "two" }()

    // Receive from whichever channel is ready first
    for i := 0; i < 2; i++ {
        select {
        case msg := <-ch1:
            fmt.Println("Received from ch1:", msg)
        case msg := <-ch2:
            fmt.Println("Received from ch2:", msg)
        }
    }

    // Timeout pattern using select + time.After
    ch := make(chan int)
    select {
    case v := <-ch:
        fmt.Println("Received:", v)
    case <-time.After(500 * time.Millisecond):
        fmt.Println("Timed out")
    }
}

Generics (Go 1.18+)

Go added generics in version 1.18 (March 2022). Type parameters use square brackets: func Map[T, U any](s []T, f func(T) U) []U. Type constraints are interfaces that specify allowed types — the built-in any constraint accepts all types; comparable accepts types that support ==. The golang.org/x/exp/slices and golang.org/x/exp/maps packages (now in standard library as of Go 1.21) use generics extensively.

Gogenerics.go
package main

import "fmt"

// Generic function — T must be comparable (supports ==)
func Contains[T comparable](s []T, val T) bool {
    for _, v := range s {
        if v == val { return true }
    }
    return false
}

// Generic Map function
func 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 constraint: only numeric types
type Number interface {
    ~int | ~int32 | ~int64 | ~float32 | ~float64
}

func Sum[T Number](s []T) T {
    var total T
    for _, v := range s { total += v }
    return total
}

func main() {
    fmt.Println(Contains([]string{"a","b","c"}, "b"))  // true
    fmt.Println(Map([]int{1,2,3}, func(x int) int { return x*x })) // [1 4 9]
    fmt.Println(Sum([]float64{1.1, 2.2, 3.3}))         // 6.6
}

Context: cancellation and deadlines

The context package propagates cancellation signals and deadlines through a call chain. Every server handler receives a context.Context as its first argument. When a request is cancelled (client disconnects, timeout exceeded), the context is cancelled, and all goroutines doing work for that request can check ctx.Done() to stop early. This prevents goroutine leaks — a common source of memory issues in Go servers.

Gocontext.go
package main

import (
    "context"
    "fmt"
    "time"
)

func doWork(ctx context.Context) error {
    select {
    case <-time.After(2 * time.Second):
        fmt.Println("Work done")
        return nil
    case <-ctx.Done():
        return ctx.Err()   // context.DeadlineExceeded or Canceled
    }
}

func main() {
    // Timeout context — auto-cancels after 1 second
    ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
    defer cancel()

    if err := doWork(ctx); err != nil {
        fmt.Println("Error:", err)   // Error: context deadline exceeded
    }
}
Commonly confused
Go does not have classes, but it has types with methods. There is no class keyword. You define a struct and attach methods to it using receiver functions. Embedding one struct in another provides composition (not inheritance). Go deliberately avoided inheritance.
Go interfaces are implicit — no "implements" keyword. A type satisfies an interface by having the right methods, whether or not it was written with that interface in mind. This enables retroactive interface satisfaction: you can define an interface in package B that types in package A satisfy, without modifying package A.
Goroutines are not OS threads and are not coroutines. They are multiplexed M:N onto OS threads by the Go runtime. Millions of goroutines can coexist using ~2KB of stack each (growing as needed). They are preemptible (since Go 1.14). This is distinct from OS threads (~1MB each) and from coroutines (which require explicit yield points).

The Go memory model

The Go memory model (go.dev/ref/mem, revised 2022) defines when a goroutine is guaranteed to observe the effects of a write by another goroutine. The model is based on the happens-before relation. Key rules: (1) a send on a channel happens before the corresponding receive; (2) a receive from an unbuffered channel happens before the send on that channel completes; (3) the closing of a channel happens before a receive that returns a zero value; (4) sync.Mutex lock/unlock happens before the next lock. The 2022 revision aligned Go's model with the C11/C++11 memory model terminology, clarifying that data races produce undefined behaviour — not just unpredictable values.

Escape analysis and heap allocation

The Go compiler performs escape analysis to determine whether variables can be stack-allocated or must escape to the heap. If a local variable's address is taken and returned from the function (or stored somewhere that outlives the function), it escapes to the heap. Stack allocation is cheap (just move the stack pointer); heap allocation requires GC tracking. Use go build -gcflags="-m" to see escape analysis decisions. Understanding escape analysis helps avoid unnecessary heap allocations in hot paths.

Go 1.21+ standard library additions and toolchain

Go 1.21 (August 2023) added the slices and maps packages to the standard library (generic sort, search, equal, clone). Go 1.22 (February 2024) fixed loop variable capture in goroutines — a longstanding footgun where all goroutines in a for loop shared the same loop variable. Go 1.26 added range over functions (iterators). The Go toolchain is self-hosting — Go is compiled by Go. The reference compiler is gc (part of the Go distribution); gccgo (GCC frontend) and TinyGo (embedded/WASM) are alternative implementations.

Specification reference

The Go Programming Language Specification. go.dev/ref/spec. Donovan, A. A. A. & Kernighan, B. W. (2015). The Go Programming Language. Addison-Wesley. The Go Memory Model (revised 2022). go.dev/ref/mem. Go Blog: go.dev/blog/ — release notes and official posts.

Sources

1
The Go Team. The Go Programming Language Specification. go.dev/ref/spec. — Authoritative language specification.
2
Donovan, A. A. A. & Kernighan, B. W. (2015). The Go Programming Language. Addison-Wesley. — The canonical Go book.
3
The Go Team. The Go Memory Model (revised 2022). go.dev/ref/mem.
4
The Go Team. Go standard library documentation. pkg.go.dev/std.
5
Go Blog. go.dev/blog/. — Official Go release announcements and deep-dives.
Source confidence: High Last verified: Primary source: Go Language Specification — go.dev/ref/spec