Go Basics #1 Getting Started and Your First Program
This series is a 7-part introductory course for people who are learning Go for the first time, or who already know another language and are coming over to Go.
- #1 Getting started and your first program ← this post
- #2 Variables, types, constants
- #3 Control flow — if/for/switch
- #4 Functions, multiple return, error type
- #5 Collections — array/slice/map
- #6 Structs and methods
- #7 Packages and modules (go mod)
This post starts with why use Go, then walks you through setup, compilation, and running your first program.
What is Go? #
Go (or Golang) is a compiled language released by Google in 2009. Its design goals are clear.
- Simple syntax — only 25 keywords, a gentle learning curve
- Fast compilation and execution — statically compiled, single-binary output
- Goroutines — a lightweight concurrency model
- Standard library — rich from the start with HTTP server, JSON, cryptography, etc.
Go shines especially in CLI tools, backend servers, and distributed systems. Infrastructure tools like Docker, Kubernetes, and Terraform are all written in Go.
Who is it a good fit for? #
If any of the following applies, Go is a good fit.
- You want to build CLI tools — easy to ship as a single binary
- HTTP server / API — robust servers using just the standard library
- Systems where concurrency matters — goroutines are the simplest answer
- You want to move from JavaScript/Python to a faster language — the learning curve is gentle
You don’t get the same low-level control as C/C++, but Go is a sweet spot between systems programming and application programming.
Compared to other languages #
A rough sense of where Go sits.
| Go | Python | JavaScript | Rust | |
|---|---|---|---|---|
| Type system | Static, inferred | Dynamic | Dynamic (TS is static) | Static, strong |
| Execution | Compiled | Interpreted | JIT | Compiled |
| Learning curve | Gentle | Gentlest | Gentle | Steep |
| Memory management | GC | GC | GC | Ownership / borrow checker |
| Concurrency | Goroutines | asyncio/threading | Event loop | async + threads |
Go takes a practical position between simplicity and performance.
Installing Go #
macOS #
brew install goLinux #
# Ubuntu/Debian
sudo apt install golang-go
# Or grab the tarball from the official site
# https://go.dev/dl/Windows #
Download the MSI installer from go.dev/dl. Or winget install GoLang.Go.
Verify the install #
go version
# prints something like: go version go1.22.0 darwin/arm64This series assumes Go 1.22 or later. We use modern features like ServeMux pattern matching and generics.
Your first program — Hello World #
Create a working folder.
mkdir hello-go
cd hello-go
go mod init hellogo mod init starts a new module. A go.mod file is created. We cover this in detail in #7 Packages and modules.
Create a main.go file with the following.
package main
import "fmt"
func main() {
fmt.Println("Hello, Go!")
}Run it.
go run main.go
# Hello, Go!go run compiles and runs in one step. If you want to produce a separate compiled binary:
go build
./hello
# Hello, Go!go build produces a binary with the same name as the module (hello). One of Go’s biggest strengths is right here — a single executable file with all dependencies statically linked in.
Walking through the code line by line #
package main
import "fmt"
func main() {
fmt.Println("Hello, Go!")
}package main— this file belongs to themainpackage. An executable program always starts at the main function in the main package.import "fmt"— imports thefmtpackage from the standard library. fmt is for I/O formatting.func main()— the entry point of the program. A function with no parameters and no return value.fmt.Println(...)— calls the Println function in the fmt package. Names exposed externally always start with an uppercase letter (a Go rule).
Go’s most distinctive syntax — semicolons and braces #
1) No semicolons #
fmt.Println("a")
fmt.Println("b")You don’t write the semicolon at the end of a line. The compiler handles it automatically. One thing to watch out for though — the opening brace must be on the same line.
// OK
func main() {
fmt.Println("hi")
}
// ✗ compile error
func main()
{
fmt.Println("hi")
}2) Indentation is tabs #
Go’s standard tool gofmt automatically formats your code. Indentation is tabs, alignment follows fixed rules. This series follows gofmt output as is.
3) Auto-formatting — go fmt
#
go fmt ./...Set up your editor to auto-format on save. The Go extension for VS Code handles this automatically.
A quick variable preview #
We cover this in detail in the next post, but just to set the tone.
package main
import "fmt"
func main() {
name := "Curtis"
age := 30
fmt.Printf("Name: %s, Age: %d\n", name, age)
}:= is shorthand syntax that declares and assigns at the same time. The type is inferred from the right-hand side (here string and int).
Mistakes caught at compile time #
A few places that surprise people new to Go.
1) Unused variables are a compile error #
func main() {
x := 10 // ✗ x declared but not used
fmt.Println("hi")
}Other languages might warn, but Go blocks compilation outright. It’s a design that forces you to keep your code tidy.
2) Unused imports are also an error #
import (
"fmt"
"strings" // ✗ "strings" imported and not used
)
func main() {
fmt.Println("hi")
}Same reason. gofmt and goimports clean these up automatically, so with a properly configured editor you barely run into them.
3) Variable shadowing — compiles but risky #
x := 10
if true {
x := 20 // a new x — shadows the outer x but compiles
fmt.Println(x) // 20
}
fmt.Println(x) // 10This isn’t a compile error, but it often causes bugs. Tools (go vet) catch some cases.
Standard tooling — the go command
#
Subcommands you’ll use often.
go run main.go # run
go build # build
go test ./... # test (all packages)
go fmt ./... # format
go vet ./... # static analysis (checks for suspicious patterns)
go mod tidy # tidy dependencies
go mod init <name> # start a new module
go get <package> # add a dependency./... means “the current directory and all subdirectories”.
Editor — VS Code + Go extension #
If you install the Go extension in VS Code, you get autocomplete, jump-to-definition, formatting, and linting. The first time you open a Go file, you’ll be prompted to install additional tools — install them all.
JetBrains’ GoLand is also popular, but VS Code alone is more than enough.
Go Playground — try it without setup #
go.dev/play is the official tool for running Go directly in your browser. Useful for trying small examples or sharing code.
Wrapping up #
What this post covered:
- Go is a language with simple syntax + static compilation + strong concurrency
- Especially well-suited for CLI tools, HTTP servers, and distributed systems
- Verify your install with
go version. The series assumes 1.22+ - Start a new project with
go mod init go run main.goorgo buildpackage main+func main()is the entry point- Externally exposed names start with an uppercase letter — Go’s visibility rule
- Unused variables/imports are compile errors
- Standard tools like
gofmt/go vetcome built in
In the next post (#2 Variables, types, constants) we cover Go’s primitive types, the different ways to declare variables, constants, and the iota pattern.