- Published on
Hello World in Go - Your First Go Program
- Authors
- Name
- Muhammad Yasir
Hello World in Go - Your First Go Program
Every programming journey begins with "Hello, World!" In Go, this simple program introduces you to the language's fundamental concepts: packages, imports, functions, and the compilation process. Let's dive deep into writing, understanding, and expanding your first Go program.
The Classic Hello World
Basic Hello World
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
Running the Program
# Save as hello.go
go run hello.go
# Output: Hello, World!
Anatomy of a Go Program
Let's break down each component of our Hello World program:
1. Package Declaration
package main
Explanation:
- Every Go file starts with a
package
declaration main
is a special package name for executable programs- Only
main
package can contain the entry point function - Other packages are used for libraries and modules
Examples:
package main // Executable program
package utils // Library package
package models // Library package
package handlers // Library package
2. Import Statement
import "fmt"
Explanation:
import
brings in external packagesfmt
(format) package provides I/O formatting functions- Standard library packages don't need module prefixes
Import Variations:
// Single import
import "fmt"
// Multiple imports (preferred)
import (
"fmt"
"os"
"time"
)
// Aliased import
import f "fmt"
// Blank import (for side effects)
import _ "database/sql"
// Dot import (imports into current namespace)
import . "fmt"
3. Main Function
func main() {
fmt.Println("Hello, World!")
}
Explanation:
func
keyword declares a functionmain()
is the entry point for executable programs- Function body is enclosed in curly braces
{}
fmt.Println()
prints text followed by a newline
Expanded Hello World Examples
Hello World with Variables
package main
import "fmt"
func main() {
message := "Hello, World!"
fmt.Println(message)
}
Hello World with User Input
package main
import (
"fmt"
"bufio"
"os"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
fmt.Print("Enter your name: ")
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
fmt.Printf("Hello, %s!\n", name)
}
Hello World with Command Line Arguments
package main
import (
"fmt"
"os"
)
func main() {
args := os.Args
if len(args) < 2 {
fmt.Println("Hello, World!")
return
}
name := args[1]
fmt.Printf("Hello, %s!\n", name)
}
Usage:
go run hello.go
# Output: Hello, World!
go run hello.go Alice
# Output: Hello, Alice!
Hello World with Time
package main
import (
"fmt"
"time"
)
func main() {
now := time.Now()
hour := now.Hour()
var greeting string
switch {
case hour < 12:
greeting = "Good morning"
case hour < 18:
greeting = "Good afternoon"
default:
greeting = "Good evening"
}
fmt.Printf("%s, World! Current time: %s\n",
greeting,
now.Format("15:04:05"))
}
Compilation and Execution
Running vs Building
go run
- Direct Execution
# Compiles and runs immediately
go run hello.go
# With multiple files
go run *.go
# With module path
go run github.com/user/repo/cmd/hello
go build
- Create Executable
# Build executable
go build hello.go
# Creates: hello (Linux/macOS) or hello.exe (Windows)
# Build with custom name
go build -o myprogram hello.go
# Build for current directory
go build .
# Build with optimizations
go build -ldflags="-s -w" hello.go
Cross-Platform Compilation
# Build for Linux
GOOS=linux GOARCH=amd64 go build hello.go
# Build for Windows
GOOS=windows GOARCH=amd64 go build hello.go
# Build for macOS
GOOS=darwin GOARCH=amd64 go build hello.go
# Build for ARM64
GOOS=linux GOARCH=arm64 go build hello.go
Execution Examples
# After building
./hello # Linux/macOS
hello.exe # Windows
# Check file size
ls -lh hello
# Output: -rwxr-xr-x 1 user user 1.8M Sep 3 10:30 hello
Understanding Go Syntax
Code Formatting
Go enforces strict formatting rules through gofmt
:
// Properly formatted Go code
package main
import "fmt"
func main() {
if true {
fmt.Println("Hello, World!")
}
}
Auto-formatting:
# Format single file
gofmt -w hello.go
# Format all Go files in directory
gofmt -w .
# Show differences without modifying
gofmt -d hello.go
Semicolons (Automatic Insertion)
// Go automatically inserts semicolons
package main
import "fmt"
func main() {
fmt.Println("Hello") // Semicolon automatically inserted
fmt.Println("World") // Semicolon automatically inserted
}
Braces Placement
// Correct - opening brace on same line
func main() {
fmt.Println("Hello")
}
// Incorrect - will cause compilation error
func main()
{
fmt.Println("Hello")
}
Common Variations and Patterns
Hello World Web Server
package main
import (
"fmt"
"net/http"
"log"
)
func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
}
func main() {
http.HandleFunc("/", helloHandler)
fmt.Println("Server starting on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
Hello World with JSON
package main
import (
"encoding/json"
"fmt"
"log"
)
type Message struct {
Text string `json:"text"`
Time string `json:"time"`
}
func main() {
msg := Message{
Text: "Hello, World!",
Time: "2025-09-03",
}
jsonData, err := json.Marshal(msg)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(jsonData))
}
Hello World with Goroutines
package main
import (
"fmt"
"time"
)
func printHello(name string) {
for i := 0; i < 3; i++ {
fmt.Printf("Hello, %s! (%d)\n", name, i+1)
time.Sleep(100 * time.Millisecond)
}
}
func main() {
go printHello("Goroutine")
printHello("Main")
// Wait for goroutine to finish
time.Sleep(500 * time.Millisecond)
}
Error Handling in Hello World
Basic Error Handling
package main
import (
"fmt"
"os"
)
func main() {
file, err := os.Open("hello.txt")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
defer file.Close()
fmt.Println("File opened successfully!")
}
Creating Custom Errors
package main
import (
"errors"
"fmt"
)
func greet(name string) error {
if name == "" {
return errors.New("name cannot be empty")
}
fmt.Printf("Hello, %s!\n", name)
return nil
}
func main() {
if err := greet(""); err != nil {
fmt.Printf("Error: %v\n", err)
}
greet("World")
}
Performance Analysis
Benchmarking Hello World
package main
import (
"fmt"
"testing"
)
func BenchmarkHelloWorld(b *testing.B) {
for i := 0; i < b.N; i++ {
fmt.Sprintf("Hello, World!")
}
}
func BenchmarkHelloWorldPrint(b *testing.B) {
for i := 0; i < b.N; i++ {
fmt.Print("Hello, World!")
}
}
Run benchmarks:
go test -bench=.
# Output:
# BenchmarkHelloWorld-8 3000000 500 ns/op
# BenchmarkHelloWorldPrint-8 1000000 1500 ns/op
Memory Usage Analysis
# Build with debug info
go build -gcflags="-m" hello.go
# Profile memory usage
go tool compile -memprofile=mem.prof hello.go
go tool pprof mem.prof
Testing Hello World
Unit Test
// hello_test.go
package main
import (
"testing"
"io"
"os"
"strings"
)
func TestHelloWorld(t *testing.T) {
// Capture stdout
old := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
// Run the function
main()
// Restore stdout
w.Close()
os.Stdout = old
// Read captured output
output, _ := io.ReadAll(r)
result := strings.TrimSpace(string(output))
expected := "Hello, World!"
if result != expected {
t.Errorf("Expected %q, got %q", expected, result)
}
}
Run tests:
go test
# Output: PASS
Industry Best Practices
Project Structure
hello-world/
├── main.go # Main application
├── main_test.go # Tests
├── go.mod # Module definition
├── go.sum # Dependency checksums
├── README.md # Documentation
├── Makefile # Build automation
└── .gitignore # Git ignore rules
go.mod Example
module github.com/username/hello-world
go 1.21
require (
github.com/stretchr/testify v1.8.4
)
Makefile
.PHONY: build test clean run
build:
go build -o bin/hello main.go
test:
go test -v
run:
go run main.go
clean:
rm -rf bin/
install:
go install
Real-World Applications
CLI Tool Structure
package main
import (
"flag"
"fmt"
"os"
)
var (
name = flag.String("name", "World", "Name to greet")
uppercase = flag.Bool("upper", false, "Use uppercase")
)
func main() {
flag.Parse()
greeting := fmt.Sprintf("Hello, %s!", *name)
if *uppercase {
greeting = strings.ToUpper(greeting)
}
fmt.Println(greeting)
}
Configuration-Based Hello World
package main
import (
"encoding/json"
"fmt"
"log"
"os"
)
type Config struct {
Message string `json:"message"`
Name string `json:"name"`
}
func main() {
file, err := os.Open("config.json")
if err != nil {
log.Fatal(err)
}
defer file.Close()
var config Config
decoder := json.NewDecoder(file)
if err := decoder.Decode(&config); err != nil {
log.Fatal(err)
}
fmt.Printf("%s, %s!\n", config.Message, config.Name)
}