Go Basics
Syntax Β· Variables & types Β· Functions Β· Structs Β· Goroutines Β· Channels Β· Defer
Sheet 1 of 2
Go 1.22+
Beginner
Printable
Go Syntax Rules
Program Structure
// Every Go file starts with package package main import "fmt" // Entry point func main() { fmt.Println("Hello, Go!") }
Imports & Multiple Packages
// Single import import "fmt" // Grouped import (preferred) import ( "fmt" "math" "strings" ) // Alias an import import f "fmt" f.Println("aliased")
Go Rules β Key Differences
// No semicolons needed (auto-inserted) // Opening { MUST be on same line // Unused imports β compile error! // Unused variables β compile error! // := infers type and declares x := 42 // short declaration var y = 42 // explicit var var z int // zero value = 0
Go philosophy: Simplicity and speed. No classes, no inheritance, no exceptions β just functions, structs, interfaces, and goroutines. The compiler enforces clean code: unused variables and imports are compile errors.
Variables & Zero Values
Declaration styles
// Short declaration (inside funcs only) name := "Alice" age := 25 active := true // var β anywhere (package level ok) var score int = 100 var pi float64 = 3.14159 // Multiple assignment a, b := 1, 2 a, b = b, a // swap!
Zero Values (default when not set)
var i int // 0 var f float64 // 0.0 var b bool // false var s string // "" (empty) var p *int // nil (pointer) // slices, maps, channels β nil
No undefined variables: Go initialises every variable to its zero value automatically β no garbage values like C/C++.
Core Data Types
| Type | Example | Notes |
|---|---|---|
| int | 42 -7 0 | Platform-sized (32 or 64-bit) |
| int8/16/32/64 | int64(1000) | Fixed-size integers |
| uint | uint(42) | Unsigned integer |
| float32 | float32(3.14) | 32-bit float |
| float64 | 3.14159 | Default decimal type β |
| bool | true false | No intβbool conversion |
| string | "hello" `raw` | UTF-8, immutable |
| byte | byte('A') β 65 | alias for uint8 |
| rune | rune('β¬') | alias for int32, Unicode codepoint |
No implicit conversion: int + float64 is a compile error. You must cast explicitly: float64(myInt) + myFloat.
Functions
Basic Function
// func name(params) returnType func add(a int, b int) int { return a + b } // Shared param type shorthand func add(a, b int) int { return a + b } // Call it result := add(3, 4) // 7
Multiple Return Values
// Go functions can return multiple values func divide(a, b float64) (float64, error) { if b == 0 { return 0, fmt.Errorf("div by zero") } return a / b, nil } // Unpack both values val, err := divide(10, 3) // Discard with blank identifier _ val, _ := divide(10, 3)
Variadic & Anonymous Functions
// Variadic β any number of args func sum(nums ...int) int { total := 0 for _, n := range nums { total += n } return total } // Anonymous function (closure) double := func(x int) int { return x * 2 } fmt.Println(double(5)) // 10
Error handling pattern: Go has no exceptions. Functions return an
error as the last return value. Always check if err != nil immediately after calling a function that can fail.Structs
Defining & Instantiating
// Define a struct type Person struct { Name string Age int } // Create instances p1 := Person{Name: "Alice", Age: 30} p2 := Person{"Bob", 25} // positional p3 := new(Person) // pointer to zero struct // Access fields fmt.Println(p1.Name) // "Alice" p1.Age = 31 // modify
Methods on Structs
// Method with value receiver func (p Person) Greet() string { return "Hi, I'm " + p.Name } // Pointer receiver β can modify func (p *Person) Birthday() { p.Age++ } p1.Birthday() fmt.Println(p1.Greet())
Arrays, Slices & Maps
Arrays & Slices
// Array β fixed size var arr [3]int = [3]int{1, 2, 3} // Slice β dynamic, preferred s := []int{1, 2, 3} s = append(s, 4, 5) s[0] // 1 s[1:3] // [2 3] β slice of slice len(s) // 5 cap(s) // capacity
Maps
// map[KeyType]ValueType m := map[string]int{ "alice": 90, "bob": 85, } m["carol"] = 92 // add/update delete(m, "bob") // delete key // Safe key lookup val, ok := m["alice"] if ok { fmt.Println(val) }
Goroutines & Channels
Goroutines β go keyword
import ( "fmt" "time" ) func sayHello(name string) { fmt.Println("Hello,", name) } func main() { // go = launch concurrently go sayHello("Alice") go sayHello("Bob") // Wait (crude β use WaitGroup in prod) time.Sleep(100 * time.Millisecond) }
Channels β typed pipes
// Create a channel ch := make(chan int) // Send in goroutine go func() { ch <- 42 // send value }() // Receive in main val := <-ch // receive value fmt.Println(val) // 42 // Buffered channel bch := make(chan int, 5) defer close(bch)
defer β runs last, LIFO order
func readFile() { f, _ := os.Open("data.txt") defer f.Close() // runs when func exits // Multiple defers β LIFO (stack) defer fmt.Println("third") defer fmt.Println("second") defer fmt.Println("first") // prints: first, second, third }
Go's superpower: Goroutines are lightweight threads managed by the Go runtime β you can run thousands concurrently with minimal memory. Channels are the safe way to communicate between goroutines: "Don't communicate by sharing memory; share memory by communicating."
Control Flow
if / else β init statement
if x > 10 { fmt.Println("big") } else if x == 10 { fmt.Println("ten") } else { fmt.Println("small") } // Init statement β scoped to if if v, ok := m["key"]; ok { fmt.Println(v) }
for β Go's only loop
// Classic C-style for i := 0; i < 5; i++ { } // while-style for x < 100 { x *= 2 } // infinite loop for { break } // range β over slice for i, v := range nums { fmt.Println(i, v) } // range β over map for k, v := range m { fmt.Println(k, v) }
fmt Package β I/O
Printing
fmt.Print("no newline") fmt.Println("with newline") fmt.Printf("Pi = %.2f\n", 3.14159) // Sprintf β return as string s := fmt.Sprintf("%s is %d", "Alice", 30) // Verbs: %v %T %d %f %s %t %p fmt.Printf("%v\n", p1) // default format fmt.Printf("%+v\n", p1) // with field names fmt.Printf("%T\n", p1) // type
Reading Input
var name string var age int // Scan reads space-separated tokens fmt.Scan(&name) fmt.Scanf("%d", &age) // bufio β read full line reader := bufio.NewReader(os.Stdin) line, _ := reader.ReadString('\n')
Naming Conventions
| What | Style | Example |
|---|---|---|
| Variable / param | camelCase | userName |
| Exported (public) | PascalCase | UserName |
| Unexported (private) | camelCase | userName |
| Function / method | camelCase | getData() |
| Struct / interface | PascalCase | UserProfile |
| Constant | PascalCase | MaxSize |
| Package | lowercase | mypackage |
| Blank identifier | _ | _, err := fn() |
Exported = public: In Go, capitalizing the first letter makes a symbol exported (visible outside its package). No
public / private keywords needed.Common Beginner Errors
Unused Variable / Import
// Compile error β unused import import "fmt" // Error if never used! // Fix: remove unused imports // Use goimports to auto-manage // Compile error β unused variable x := 42 // Error if x never read! // Fix: use _ to explicitly discard _ = x
Nil Pointer & Map Init
// Nil pointer dereference var p *Person p.Name // PANIC! p is nil // Fix: p = &Person{} // Assignment to nil map var m map[string]int m["key"] = 1 // PANIC! // Fix: m = make(map[string]int)
Goroutine / Channel Deadlock
// Deadlock β nothing reads from ch ch := make(chan int) ch <- 42 // blocks forever! // Fix: read in a goroutine go func() { ch <- 42 }() val := <-ch // Forgot to close channel defer close(ch) // always close!
Go Basics Mastery Checklist
| Syntax & Setup | Key point |
|---|---|
| Write a valid Go program | package main + func main() |
| Declare variables two ways | := vs var |
| Understand zero values | 0, false, "" |
| Import and use packages | import "fmt" |
| Functions & Structs | Key point |
|---|---|
| Write functions with multiple returns | return val, err |
| Define and use structs | type X struct{} |
| Attach methods | func (r Recv) Name() |
| Use slices and maps | append Β· make Β· range |
| Concurrency | Key point |
|---|---|
| Launch a goroutine | go funcName() |
| Send / receive on channel | ch <- v / <-ch |
| Use defer for cleanup | defer f.Close() |
| Check errors properly | if err != nil |
Next up β Sheet 2: Go Concurrency Β·
Goroutines Β· WaitGroups Β· Mutex Β· select Β· channels patterns Β· context β deep dive into Go's concurrency model with real-world patterns.