Go, End to End
The Absolute Basics
Every Go program starts life as a package. The file that produces a runnable binary declares package main and defines a func main() with no parameters and no return value. That's the entire entry-point contract, nothing more to configure.
Three commands cover almost everything you'll do day to day. go run main.go compiles and runs in one step, throwing away the binary afterward, good for quick iteration. go build compiles into a binary in the current directory and leaves it there. go install does the same but places the binary in your GOPATH/bin (or GOBIN), so it ends up on your PATH if that's configured, useful for tools you want available everywhere.
Imports
An import block lists the packages a file depends on. The standard library path is just the package name for single-word packages (fmt, os, strings) and a slash-separated path for nested ones (net/http, encoding/json). Go is strict about this: importing a package and not using it is a compile error, not a warning. There's no such thing as an unused import lingering in committed code.
import (
"fmt"
"os"
"strings"
)No semicolons, mandatory braces
Go statements don't end in semicolons in the source you write. The compiler inserts them automatically based on a simple rule (a semicolon gets added at the end of a line if the last token could end a statement), which is also why the opening brace of a block has to be on the same line as whatever it belongs to. Put it on the next line and the automatic semicolon insertion breaks your function.
Putting { on its own line after func main() or if true is a real compile error in Go, not a style nit. The formatter (gofmt) enforces brace placement along with everything else, which is part of why Go code across different codebases looks so similar.
Variables and zero values
var x int declares a variable with an explicit type. Left uninitialized, it gets that type's zero value, not garbage memory: 0 for numbers, "" for strings, false for bools, nil for pointers/slices/maps/interfaces/channels/functions. This is a real safety guarantee, not a convention, every variable is always in a valid, defined state.
Inside a function, := declares and initializes in one step, inferring the type from the right-hand side. It's the idiomatic default for local variables. var is for when you want to be explicit about the type, when you're declaring without initializing, or at package level (:= only works inside functions).
Constants and iota
const declares a compile-time constant. Constants can't be reassigned, and untyped numeric constants (like const Pi = 3.14159) can be used anywhere a compatible numeric type is expected without an explicit conversion, which typed variables can't do.
iota is Go's mechanism for auto-incrementing values inside a const block, most commonly used to build enumerations. It resets to 0 at the start of each const block and increments by one on each subsequent line.
Try it yourself: add a String() method to Weekday (a switch over the value returning the day's name) and print Wednesday again. This is the standard pattern for readable enums in Go, since Go has no built-in enum type with named printing.