In the previous tutorial, you learned what Go is and why it is a great language to learn. Now it is time to install Go and write your first program.
This tutorial covers installation on all three major platforms. You will also set up VS Code and learn the basic Go commands.
Try Go Online First
Before installing anything, you can try Go in your browser. The Go Playground lets you write and run Go code online:
This is great for quick experiments. But for real development, you need Go installed on your computer.
Installing Go
macOS
The easiest way to install Go on macOS is with Homebrew:
# Install Go with Homebrew
brew install go
# Verify the installation
go version
You should see something like:
go version go1.24.1 darwin/arm64
If you don’t use Homebrew, download the installer from go.dev/dl. Download the .pkg file and run it.
Linux
On Ubuntu or Debian:
# Download Go (check go.dev/dl for the latest version)
wget https://go.dev/dl/go1.24.1.linux-amd64.tar.gz
# Remove any old installation and extract
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.24.1.linux-amd64.tar.gz
# Add Go to your PATH (add this to ~/.bashrc or ~/.zshrc)
export PATH=$PATH:/usr/local/go/bin
# Verify
go version
Windows
- Download the
.msiinstaller from go.dev/dl - Run the installer
- Open a new Command Prompt or PowerShell
- Run
go versionto verify
The installer adds Go to your PATH automatically.
Setting Up VS Code
VS Code is the most popular editor for Go development. Here is how to set it up:
- Install VS Code if you don’t have it
- Open VS Code
- Go to Extensions (Ctrl+Shift+X or Cmd+Shift+X)
- Search for “Go” by the Go team at Google
- Click Install
The Go extension gives you:
- Code completion (IntelliSense)
- Automatic imports
- Error checking as you type
- Formatting on save
- Debugging support
- Test runner
After installing the extension, open the command palette (Ctrl+Shift+P or Cmd+Shift+P) and run Go: Install/Update Tools. Click “Select All” and then “OK”. This installs the Go tools that the extension needs.
Your First Go Module
Every Go project starts with a module. A module is a collection of Go packages. Think of it as a project folder with a name.
Create a new folder and initialize a Go module:
# Create a project folder
mkdir hello-go
cd hello-go
# Initialize a Go module
go mod init hello-go
This creates a go.mod file:
module hello-go
go 1.24.1
The go.mod file tracks your module name and Go version. It will also track your dependencies later.
Hello World
Create a file called main.go:
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
Run it:
go run main.go
Output:
Hello, World!
Let me explain what go run does. It compiles your code and runs it in one step. It does not create a permanent binary file. For that, you use go build:
# Build a binary
go build -o hello main.go
# Run the binary
./hello
Now you have a compiled binary called hello. You can copy this file to any computer with the same operating system and run it. No Go installation needed on that machine.
Understanding the Code
Let me break down the Hello World program:
package main
Every Go file starts with a package declaration. The main package is special. It tells Go “this is an executable program, not a library.”
import "fmt"
The import statement loads packages you need. The fmt package provides formatting and printing functions. It is part of Go’s standard library.
func main() {
fmt.Println("Hello, World!")
}
The main function is where your program starts. Every executable Go program must have a main function in the main package.
fmt.Println prints a line of text. The Println starts with a capital letter. In Go, this means the function is exported (public). Functions that start with a lowercase letter are private to their package.
Printing and Formatting
The fmt package has several printing functions. Let me show you the most useful ones:
package main
import "fmt"
func main() {
name := "Alex"
age := 25
height := 1.75
// Println — print with a newline at the end
fmt.Println("Hello,", name)
// Printf — formatted printing (like C's printf)
fmt.Printf("Name: %s, Age: %d, Height: %.2f\n", name, age, height)
// Sprintf — format a string without printing it
message := fmt.Sprintf("%s is %d years old", name, age)
fmt.Println(message)
// Print — print without a newline
fmt.Print("First ")
fmt.Print("Second ")
fmt.Println("Third")
}
Output:
Hello, Alex
Name: Alex, Age: 25, Height: 1.75
Alex is 25 years old
First Second Third
The most common format verbs are:
| Verb | Description | Example |
|---|---|---|
%s | String | "Alex" |
%d | Integer | 25 |
%f | Float | 1.750000 |
%.2f | Float with 2 decimals | 1.75 |
%v | Any value (default format) | Works with any type |
%T | Type of a value | string, int |
%t | Boolean | true |
\n | Newline | — |
The %v verb is very useful. It works with any type and prints a reasonable default:
package main
import "fmt"
func main() {
fmt.Printf("String: %v\n", "hello")
fmt.Printf("Number: %v\n", 42)
fmt.Printf("Boolean: %v\n", true)
fmt.Printf("Float: %v\n", 3.14)
}
Output:
String: hello
Number: 42
Boolean: true
Float: 3.14
Reading User Input
You can read input from the user with fmt.Scan or fmt.Scanf:
package main
import "fmt"
func main() {
var name string
var age int
fmt.Print("What is your name? ")
fmt.Scan(&name)
fmt.Print("How old are you? ")
fmt.Scan(&age)
fmt.Printf("Hello, %s! You are %d years old.\n", name, age)
}
The & before name and age is the address operator. It gives Scan the memory location where it should store the input. Don’t worry about this detail now. We will cover pointers later in this series.
For reading a full line (with spaces), use bufio.Scanner:
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
fmt.Print("Enter a sentence: ")
scanner.Scan()
text := scanner.Text()
fmt.Printf("You typed: %s\n", text)
fmt.Printf("Length: %d characters\n", len(text))
}
A Complete Example
Let me put everything together in a small program:
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
fmt.Println("=== GO-2: Your First Go Program ===")
fmt.Println()
// Get user input
fmt.Print("What is your name? ")
scanner.Scan()
name := scanner.Text()
// Greet the user
greeting := fmt.Sprintf("Hello, %s!", strings.Title(name))
fmt.Println(greeting)
// Print some info
fmt.Printf("Your name has %d characters\n", len(name))
fmt.Printf("Uppercase: %s\n", strings.ToUpper(name))
fmt.Printf("Lowercase: %s\n", strings.ToLower(name))
// Multiple values
first, last := splitName(name)
fmt.Printf("First: %s, Last: %s\n", first, last)
}
// splitName splits a full name into first and last name
func splitName(fullName string) (string, string) {
parts := strings.Fields(fullName)
if len(parts) < 2 {
return fullName, ""
}
return parts[0], parts[len(parts)-1]
}
Run it:
go run main.go
This example uses:
fmtfor printing and formattingbufiofor reading user inputstringsfor string manipulation- A custom function with multiple return values
- The
:=short variable declaration
Essential Go Commands
Here are the Go commands you will use every day:
# Run a Go file (compile + execute in one step)
go run main.go
# Build a binary
go build -o myapp main.go
# Initialize a new module
go mod init myproject
# Download dependencies
go mod tidy
# Format your code (Go has one official style)
go fmt ./...
# Run tests
go test ./...
# Check for common mistakes
go vet ./...
The go fmt command is important. Go has one official code style. Every Go developer uses the same formatting. No arguments about tabs vs spaces. No config files. Just run go fmt and your code looks like everyone else’s.
Project Structure
Your project now looks like this:
hello-go/
go.mod
main.go
This is a valid Go project. For small programs, this is all you need. As your projects grow, you will add more files and packages. We will cover project structure later in the series.
Common Mistakes
1. Unused imports are errors in Go.
import "fmt"
import "os" // Error: "os" imported and not used
func main() {
fmt.Println("Hello")
}
Go does not allow unused imports. Remove them, or use the blank identifier _:
import _ "os" // This tells Go: "I imported this on purpose"
In practice, VS Code removes unused imports automatically when you save.
2. Unused variables are errors too.
func main() {
name := "Alex" // Error: name declared and not used
}
Go forces you to use every variable you declare. This keeps your code clean.
3. Exported names start with a capital letter.
fmt.Println("Hello") // Works — Println is exported (capital P)
fmt.println("Hello") // Error — println is not exported (lowercase p)
This is how Go does public vs private. Capital letter = public. Lowercase = private.
Source Code
You can find the complete source code for this tutorial on GitHub:
Related Articles
- Go Tutorial #1: What is Go? — Overview of Go and why to learn it
What’s Next?
In the next tutorial, Go Tutorial #3: Variables, Types, and Constants, you will learn:
- How to declare variables with
varand:= - All the basic types in Go
- Zero values — why Go has no
nullfor basic types - Constants and
iota - Type conversions
This is part 2 of the Go Tutorial series. Follow along to learn Go from scratch.