Skip to content
Codeloom
Go

Install Go and Write Your First Program

A complete setup guide for Go on macOS, Linux, and Windows — install the toolchain, verify with go version, create a module, and run a real program with go run and go build.

·9 min read · By Codeloom
Beginner 9 min read

What you'll learn

  • How to install Go on macOS, Linux, and Windows
  • How to verify your install with go version
  • What a Go module is and how to create one with go mod init
  • The anatomy of every Go program — package main, imports, func main
  • The difference between go run and go build, and when to use each

Prerequisites

This post takes you from no Go on your machine to a working program in about ten minutes. We cover all three major operating systems, the module system you’ll use for every project after this one, and the two commands — go run and go build — that you’ll lean on every day.

Installing Go

The official installer at go.dev/dl is the source of truth. Avoid third-party bundles unless you have a strong reason; Go’s installer is small, fast, and well-maintained.

macOS

The simplest path is the official .pkg installer:

  1. Visit go.dev/dl.
  2. Download the darwin-arm64.pkg (Apple Silicon) or darwin-amd64.pkg (Intel Mac).
  3. Double-click and follow the prompts.

If you prefer Homebrew:

brew install go

Homebrew tracks the latest stable Go closely, and brew upgrade go keeps you current.

Linux

On Debian, Ubuntu, and derivatives, the system package is often out of date. Prefer the official tarball:

# download (replace the version with the latest from go.dev/dl)
curl -LO https://go.dev/dl/go1.23.0.linux-amd64.tar.gz

# remove any old install and extract into /usr/local
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.23.0.linux-amd64.tar.gz

Then add Go to your PATH by appending one line to ~/.bashrc or ~/.zshrc:

export PATH=$PATH:/usr/local/go/bin

Reload your shell:

source ~/.bashrc

On Arch, sudo pacman -S go is current. On Fedora, sudo dnf install golang is usually fine.

Windows

  1. Visit go.dev/dl and download windows-amd64.msi.
  2. Run the installer. Accept the default install path (C:\Program Files\Go).
  3. The installer adds Go to your PATH automatically.

Open a new PowerShell or Command Prompt window after install. Existing terminal sessions won’t see the updated PATH.

Verify the install

Open a terminal and run:

go version
# output: go version go1.23.0 darwin/arm64

If you see a version line, you’re done. If your shell says command not found, your PATH isn’t picking up the install — re-open the terminal, or re-check the export line on Linux.

Picking an editor

Any editor works, but two are most common:

  • VS Code with the official Go extension by the Go Team. Free, fast, and the extension auto-installs the language server (gopls) and supporting tools the first time you open a .go file.
  • GoLand from JetBrains. Paid, but excellent if you already use other JetBrains IDEs.

The rest of this series uses VS Code in screenshots when needed, but everything works the same in any editor.

Your first program (the quick version)

Make a folder and a file:

mkdir hello
cd hello

Create main.go with this content:

package main

import "fmt"

func main() {
    fmt.Println("Hello, Go!")
}

Run it:

go run main.go
# output: Hello, Go!

That works without any project setup. For one-file experiments, go run is enough. Real projects use a module, which we set up next.

What is a Go module?

A module is a collection of Go packages that are versioned and released together. It’s roughly Go’s answer to package.json in Node or pyproject.toml in Python. Every project you build will be a module.

The module is defined by a single file at the project root called go.mod. You create it with go mod init, passing a module path: a string that uniquely identifies the project, conventionally the import path of its repository.

mkdir greeter
cd greeter
go mod init example.com/greeter
# output: go: creating new go.mod: module example.com/greeter

You now have a go.mod file:

cat go.mod
# output:
# module example.com/greeter
#
# go 1.23

The path doesn’t have to resolve to a real domain for local work — example.com/greeter is fine. When you publish a module, the path is usually the actual repo URL (github.com/your-name/greeter). We’ll cover modules properly later in the series.

Your first program (the proper version)

Inside the greeter folder, create main.go:

package main

import "fmt"

func main() {
    name := "world"
    fmt.Printf("Hello, %s!\n", name)
}

Run it:

go run .
# output: Hello, world!

Notice the difference: go run . tells Go to run the current module’s main package. You don’t have to name the file. As your projects grow into multiple files, this is how you’ll run them.

Anatomy of every Go program

Look at the file again. Every line is doing real work.

package main

The package this file belongs to. The special name main makes it an executable. Any other name produces a library — code other packages can import but cannot run on its own.

import "fmt"

Brings in the standard library’s fmt package. Go’s import statement is strict: if you import something and don’t use it, the program won’t compile. This catches a lot of dead code automatically.

func main() {
    ...
}

func declares a function. main is the program’s entry point — the one place Go starts execution. It takes no arguments and returns nothing.

name := "world"

The := operator declares a new variable and infers its type from the value on the right. Here name is a string. We cover variable declarations properly in Variables and Basic Types in Go.

fmt.Printf("Hello, %s!\n", name)

Printf is formatted print. %s is a placeholder for a string. The \n is an explicit newline — unlike Println, Printf doesn’t add one for you.

go run vs go build

These two commands are the daily-driver pair.

go run compiles your code into a temporary binary, runs it, and discards the binary when it exits:

go run .
# output: Hello, world!

This is the fast feedback loop while developing. There’s no artifact to clean up.

go build compiles your code into an executable file in the current directory:

go build
ls
# output: go.mod  greeter  main.go

The binary is named after the module’s last path segment by default — here, greeter. You can run it directly:

./greeter
# output: Hello, world!

That file is self-contained. You can copy it to another machine with the same OS and architecture and it will run, with no Go installation required. This is one of Go’s signature features.

To control the output name:

go build -o hello
./hello
# output: Hello, world!

To cross-compile for another platform — say, a Linux server from your Mac:

GOOS=linux GOARCH=amd64 go build -o hello-linux

Now you have a Linux binary you can scp to a server and run.

Try this. Change the message in main.go, then run go run .. Now run go build, then ./greeter. Confirm the rebuilt binary has the new message. Finally, run go build -o say-hi and check that you have a binary called say-hi that prints the same message. Three commands, three checkpoints.

A slightly bigger first program

To make main.go feel like a real program rather than a one-liner, expand it:

package main

import (
    "fmt"
    "os"
)

func main() {
    name := "world"
    if len(os.Args) > 1 {
        name = os.Args[1]
    }
    fmt.Printf("Hello, %s!\n", name)
}

Two new things:

  • import ( ... ) groups multiple imports. This is the common form once you have more than one.
  • os.Args is the list of command-line arguments. os.Args[0] is the program name itself; os.Args[1] is the first user-supplied argument.

Run it both ways:

go run .
# output: Hello, world!

go run . Yash
# output: Hello, Yash!

That’s a real command-line tool, in fourteen lines. Build it and you have a binary you could ship.

Common install problems

A handful of things trip beginners up.

go: command not found on Linux usually means /usr/local/go/bin isn’t on your PATH. Re-check your shell config and open a new terminal.

go: cannot find main module means you ran go run . somewhere without a go.mod. Either run go mod init in that folder, or pass the filename directly: go run main.go.

An old Go version — anything older than 1.21 — will lack features used throughout this series. Run go version; if it’s behind, reinstall.

Editor doesn’t know Go. In VS Code, open a .go file and accept the prompt to install Go tools. If you skipped it, run the command palette: Go: Install/Update Tools and tick everything.

What just happened?

In about ten minutes you have:

  • A current Go toolchain on your machine.
  • A folder that is a real Go module.
  • A program that takes a command-line argument, formats it, and prints it.
  • A compiled binary you could deploy anywhere with the same OS and architecture.

Everything from here is building on those four things.

Recap

You now know:

  • The Go toolchain is installed from go.dev/dl on every OS; go version verifies it.
  • A module is created with go mod init <module-path>, producing a go.mod file at the project root.
  • Every program needs package main, at least one import, and a func main().
  • go run . compiles and runs in one step; go build produces a standalone binary; GOOS=... GOARCH=... go build cross-compiles.

Next steps

The next post covers Go’s variables and basic types — var versus :=, the numeric and string types, zero values, type conversions, and constants. After that, you have enough to write real programs that take input, do work, and print results.

→ Next: Variables and Basic Types in Go

Questions or feedback? Email codeloomdevv@gmail.com.