Files

292 lines
8.5 KiB
Markdown
Raw Permalink Normal View History

2026-07-16 10:13:46 +03:30
# 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.