Files
go-simple-api/lessons/00-go-basics-1-syntax-and-types.md
2026-07-16 10:13:46 +03:30

8.5 KiB

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. Confirm it worked:

go version

You should see something like go version go1.26.x.

Make a folder and your first program:

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

package main

import "fmt"

func main() {
	fmt.Println("hello, world")
}

Run it:

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.

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): int0, string"" (empty string), boolfalse, pointers → nil (explained in Part 2).

Type conversion

Go never silently converts between types (unlike JavaScript or PHP). You must convert explicitly:

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

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):

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

// 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

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

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:

// 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.