Go
01 / 04

Core Language

Go — Core Language

Basics

package main

import (
    "fmt"
    "strings"
    "strconv"
)

func main() {
    // Variable declaration
    var name string = "Alice"
    age := 28               // short declaration (type inferred)
    var x, y int = 1, 2
    var isActive = true

    // Zero values: int=0, float=0.0, bool=false, string=""

    // Constants
    const Pi = 3.14159
    const (
        StatusOK    = 200
        StatusNotFound = 404
    )

    // Type conversion (explicit, no implicit)
    n := 42
    f := float64(n)
    s := strconv.Itoa(n)    // int to string
    n2, err := strconv.Atoi("42")  // string to int

    // String operations
    fmt.Println(len(name))
    fmt.Println(strings.ToUpper(name))
    fmt.Println(strings.Contains(name, "Ali"))
    fmt.Println(strings.Split("a,b,c", ","))
    fmt.Sprintf("Hello, %s! You are %d.", name, age)
}

Control Flow

// If — can include an init statement
if x > 0 {
    fmt.Println("positive")
} else if x < 0 {
    fmt.Println("negative")
} else {
    fmt.Println("zero")
}

// If with init statement
if val, err := strconv.Atoi("42"); err == nil {
    fmt.Println(val * 2)
}

// For — Go's only loop
for i := 0; i < 10; i++ { ... }         // C-style
for i < 10 { i++ }                       // while-style
for { break }                             // infinite loop

// Range
nums := []int{1, 2, 3}
for i, v := range nums { fmt.Println(i, v) }
for _, v := range nums { fmt.Println(v) }  // ignore index

m := map[string]int{"a": 1}
for k, v := range m { fmt.Println(k, v) }

// Switch — no fallthrough by default
switch day {
case "Mon", "Tue", "Wed", "Thu", "Fri":
    fmt.Println("weekday")
case "Sat", "Sun":
    fmt.Println("weekend")
default:
    fmt.Println("unknown")
}

// Switch with no condition (like if-else chain)
switch {
case x < 0:
    fmt.Println("negative")
case x == 0:
    fmt.Println("zero")
default:
    fmt.Println("positive")
}

Functions

// Multiple return values
func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, fmt.Errorf("division by zero")
    }
    return a / b, nil
}

result, err := divide(10, 3)
if err != nil {
    log.Fatal(err)
}

// Named return values
func minMax(arr []int) (min, max int) {
    min, max = arr[0], arr[0]
    for _, v := range arr[1:] {
        if v < min { min = v }
        if v > max { max = v }
    }
    return  // naked return
}

// Variadic
func sum(nums ...int) int {
    total := 0
    for _, n := range nums {
        total += n
    }
    return total
}
sum(1, 2, 3)
nums := []int{1, 2, 3}
sum(nums...)   // spread slice

// First-class functions
add := func(a, b int) int { return a + b }
apply := func(f func(int, int) int, a, b int) int { return f(a, b) }

// Defer — runs when function returns (LIFO order)
func readFile(path string) {
    f, _ := os.Open(path)
    defer f.Close()    // guaranteed cleanup
    // ... use f
}

Data Structures

// Arrays (fixed size)
var a [3]int = [3]int{1, 2, 3}
b := [...]int{1, 2, 3}   // size inferred

// Slices (dynamic, reference to underlying array)
s := []int{1, 2, 3}
s = append(s, 4, 5)
s2 := s[1:3]             // slice [2, 3] — shares memory!
s3 := make([]int, 5)     // len=5, cap=5
s4 := make([]int, 0, 10) // len=0, cap=10

copy(dst, src)           // copy elements
len(s), cap(s)

// Maps
m := map[string]int{"a": 1, "b": 2}
m["c"] = 3
val, ok := m["a"]    // ok=false if key missing
delete(m, "b")

m2 := make(map[string][]string)

// Structs
type User struct {
    ID       int
    Name     string
    Email    string
    IsActive bool
}

u := User{ID: 1, Name: "Alice", Email: "a@b.com"}
u2 := User{1, "Bob", "b@b.com", true}  // positional (avoid)
fmt.Println(u.Name)

// Struct embedding (composition over inheritance)
type Admin struct {
    User            // embed User fields/methods
    Level int
}
admin := Admin{User: u, Level: 5}
fmt.Println(admin.Name)   // promoted field

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free