# Go Basics, Part 1 — Syntax, Types, and Control Flow This is the first of three "Go Basics" lessons. If you've never written Go before, do all three before starting Lesson 1 of the main course. If you already know another programming language (Python, JavaScript, PHP, Java, C, etc.), you'll move through this fast — Go is a small, simple language on purpose. ## 1. Installing Go and running your first program Download and install Go from [go.dev/dl](https://go.dev/dl/). Confirm it worked: ```bash go version ``` You should see something like `go version go1.26.x`. Make a folder and your first program: ```bash mkdir hello && cd hello go mod init hello ``` `go mod init hello` creates a `go.mod` file — this marks the folder as a **Go module** (a self-contained project with its own dependencies). We'll explain modules properly in Part 3; for now, just know every Go project needs one. **`main.go`** ```go package main import "fmt" func main() { fmt.Println("hello, world") } ``` Run it: ```bash go run . ``` You should see `hello, world` printed. Let's break down every single piece of that file, since you'll type this pattern constantly: - `package main` — every Go file starts by declaring which **package** it belongs to. A package is just a folder of `.go` files that are compiled together and can freely call each other's code. `package main` is special: it means "this produces a runnable program," not a reusable library. - `import "fmt"` — pulls in the standard library's `fmt` package (short for "format"), which has functions for printing text and formatting strings. - `func main()` — the function named `main`, inside `package main`, is the **entry point**. When you run the compiled program, execution starts here. There must be exactly one `main` function in `package main`. - `fmt.Println("hello, world")` — calls the `Println` function from the `fmt` package (note the dot: `package.Function`), passing it the string `"hello, world"`. `Println` prints its arguments followed by a newline. Two ways to run Go code: - `go run .` (or `go run main.go`) — compiles and runs immediately, doesn't leave a binary behind. Good for development. - `go build .` — compiles into an actual executable file (e.g. `hello` or `hello.exe`) that you can run directly (`./hello`) without Go installed on the machine that runs it. This is what you'd do to ship the program. ## 2. Variables and basic types Go is **statically typed**: every variable has a fixed type, decided either explicitly or by inference, and that type never changes. ```go package main import "fmt" func main() { // Explicit type var age int = 30 // Type inferred from the value (int, since 30 has no decimal point) var name = "Hamid" // The short declaration operator ":=" — declares AND assigns in one // step, inferring the type. This is by far the most common way to // declare variables inside a function body. city := "Tehran" height := 1.78 // inferred as float64 fmt.Println(age, name, city, height) // Reassignment - no "var" or ":=" needed, the variable already exists age = 31 fmt.Println(age) // Multiple variables at once var x, y int = 1, 2 a, b := 3, 4 fmt.Println(x, y, a, b) } ``` Key rules: - `:=` can ONLY be used to declare a **new** variable (usually inside a function). It's shorthand for `var x = value` with the type inferred. - `var` can be used with or without an initial value: `var count int` declares `count` as an `int` with the **zero value** `0` (Go always initializes variables — there's no "undefined" or garbage value). - You cannot declare a variable and never use it — Go's compiler will refuse to build code with an unused local variable. This trips up everyone coming from other languages at first. ### The built-in types you'll use constantly | Type | Example | Notes | |---|---|---| | `int` | `42` | Platform-dependent size (64-bit on modern machines); use this by default for whole numbers | | `string` | `"hello"` | UTF-8 text, immutable | | `bool` | `true`, `false` | | | `float64` | `3.14` | Default type for decimal numbers | | `byte` | | Alias for `uint8`, used for raw binary data | | `[]byte` | | A "slice of bytes" — how Go represents raw binary data (we cast strings to this constantly, e.g. for password hashing) | Zero values (what a variable holds if declared without an initial value): `int` → `0`, `string` → `""` (empty string), `bool` → `false`, pointers → `nil` (explained in Part 2). ### Type conversion Go **never** silently converts between types (unlike JavaScript or PHP). You must convert explicitly: ```go var i int = 42 var f float64 = float64(i) // must explicitly convert int -> float64 var s string = fmt.Sprintf("%d", i) // int -> string via formatting id := "123" // s, err := strconv.Atoi(id) // string -> int, using the strconv package ``` You'll see this constantly in the main course, e.g. `int(id)` when converting a database's `int64` auto-increment ID into our own `int` field. ## 3. `if`, `for`, and `switch` Go has exactly one looping construct — `for` — no `while`, no `do-while`. It also does **not** use parentheses around conditions, but curly braces `{ }` are always required (even for a single-line body). ### `if` ```go age := 20 if age >= 18 { fmt.Println("adult") } else if age >= 13 { fmt.Println("teenager") } else { fmt.Println("child") } ``` A very common Go idiom: declaring a variable that's scoped ONLY to the `if`/`else` block, often used with error handling (you'll see this constantly starting in Part 2): ```go if err := doSomething(); err != nil { fmt.Println("failed:", err) } // err doesn't exist out here — it was scoped to the if statement ``` ### `for` — Go's only loop ```go // Classic three-part loop (like C's for) for i := 0; i < 5; i++ { fmt.Println(i) } // "while" style - just the condition count := 0 for count < 3 { fmt.Println("counting:", count) count++ } // Infinite loop - break out manually for { fmt.Println("runs forever until break") break } // Looping over a collection (slices, maps - covered in Part 3) names := []string{"alice", "bob", "carol"} for index, name := range names { fmt.Println(index, name) } // If you don't need the index, use _ (the "blank identifier") to // explicitly discard it - Go's compiler complains about unused // variables, and _ is the escape hatch: for _, name := range names { fmt.Println(name) } ``` You'll see `_` constantly throughout the main course — any time a function returns something you genuinely don't need, `_` discards it without triggering an "unused variable" error. ### `switch` ```go day := "Monday" switch day { case "Saturday", "Sunday": fmt.Println("weekend") default: fmt.Println("weekday") } ``` Unlike C/Java, Go's `switch` cases do **not** fall through by default — each case automatically breaks after its block, no `break` statement needed. ## 4. Strings, formatting, and comments ```go name := "Hamid" age := 31 // Println - space-separated, newline at the end fmt.Println("name:", name, "age:", age) // Printf - C-style format string, YOU add the newline with \n fmt.Printf("name: %s, age: %d\n", name, age) // Sprintf - same as Printf but returns a string instead of printing it message := fmt.Sprintf("hello %s, you are %d years old", name, age) fmt.Println(message) ``` Common format verbs you'll use throughout the course: | Verb | Meaning | |---|---| | `%s` | string | | `%d` | integer | | `%f` | float | | `%v` | "default" representation of any value — great for debugging | | `%+v` | like `%v` but includes struct field names | | `%w` | wraps an error (covered in Part 3) — only valid with `fmt.Errorf` | Comments: ```go // A single-line comment /* A multi-line comment. */ // A comment directly above a function/type, with no blank line between, // is a DOC comment - tools display it as that function's documentation. // This project's code uses these constantly. func DoSomething() {} ``` ## 5. Try it yourself Before moving to Part 2, write a small standalone program (new folder, `go mod init practice`, `main.go`) that: 1. Declares a `string` name and an `int` age using `:=`. 2. Uses `if`/`else if`/`else` to print a different message depending on the age (e.g. "minor", "adult", "senior" for under 18 / under 65 / 65+). 3. Uses a `for` loop to print the numbers 1 through 10. 4. Uses `fmt.Printf` to print the name and age formatted into one sentence. Run it with `go run .`. Once this feels natural, move to Part 2 — functions, structs, and pointers, which is where Go starts looking like the code you'll write in the actual course.