Search and navigate

Pages

Start HereRoadmapTutorialsCheatsheetInterview QuestionsResources

Published tutorials

Building a REST API with Go: The Complete TutorialError Handling in Go: Wrapping, Classification, and APIsFan-Out Fan-In in Go: Parallel Work with ChannelsFuzz Testing in Go: Finding Bugs AutomaticallyGeneric Functions in Go: Writing Reusable CodeGin in Go: Build and Test a Small JSON APIGo Benchmarking: Measuring Performance with testing.BGo Channel Patterns: Advanced Recipes That WorkGo Channels: Communication Between GoroutinesGo Concurrency Patterns: A Practical CatalogueGo Constraints: comparable, Ordered and Custom SetsGo Context: Cancellation, Deadlines, and Request ValuesGo defer: Cleanup, Ordering, and Common TrapsGo HTTP Client: Timeouts, JSON, and Reliable RequestsGo HTTP Middleware: Build a Production ChainGo Interview Questions: 25 Answers That Show UnderstandingGo Mutex: Protecting Shared State from Race ConditionsGo net/http: Build an HTTP Server from ScratchGo select Statement: Multiplexing Channels ExplainedGo Tools You Need for a Reliable Development LoopGo Tutorial: From First Program to Backend FoundationsGo Type Parameters: Syntax and Constraints ExplainedGo Worker Pool Pattern: Bounded Concurrency at ScaleGo's Type System Deep Dive: Static Typing Done RightGolang Compilation and Execution ExplainedGolang Developer Salary 2026: US, UK and RemoteGolang File Structure for Modules and ApplicationsGolang Hello World and Your First Go ProgramGolang IDEs: Choose an Editor for Your WorkflowGolang Interfaces: What They Are and How to Use ThemGoroutine Leaks in Go: How to Detect and Prevent ThemGoroutines in Go: Concurrency Without LeaksHow to Download and Install Golang SafelyHow to Learn Golang with a Focused Study PlanIntegration Testing in Go: Testing Real BoundariesJSON in Go: Encoding, Decoding, and ValidationLearn Golang with a Practical Beginner CourseMocking in Go: Test Doubles Without Magicsync.WaitGroup in Go: Coordinating Multiple GoroutinesTable-Driven Tests in Go: The Idiomatic WayTesting in Go: Table Tests, HTTP, Fakes, and CoverageWhat Is Go and How Does a Go Program Work?Why Learn Golang and What Is Go Used For?Writing Unit Tests in Go: A Practical Guide
Open full search and filters →

Go Tutorial: From First Program to Backend Foundations

Learn Go fundamentals through a practical path covering setup, types, functions, structs, errors, concurrency, testing, and HTTP.

Standard-library lessonGo requirement: Go 1.22+How tutorials are checked
Fundamentals · Lesson 15Saved in this browser. No account required.

Go is a compiled language designed for understandable programs, fast builds, and practical concurrency. This tutorial gives you the mental model and sequence needed to start building backend services.

Reviewer’s note: This is the site’s foundational Go path for beginners. The examples establish the toolchain, language basics, error handling, concurrency, testing, and HTTP foundations that the deeper tutorials build on.

Install Go and verify the toolchain

Install Go from the official site, then check the version:

go version

Create a module and first program:

mkdir hello-go
cd hello-go
go mod init example.com/hello-go
package main

import "fmt"

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

Run it with go run .; format it with go fmt ./...; test it with go test ./....

Variables, control flow, and functions

Go infers local variable types with := while package-level declarations use var. The zero value makes every declared variable usable.

func priceWithTax(price float64, rate float64) float64 {
	return price * (1 + rate)
}

total := priceWithTax(20, 0.12)
if total > 20 {
	fmt.Println("tax applied")
}

Go has one loop keyword, for, which covers counting, conditions, and ranges. Prefer small functions with explicit inputs and outputs.

Model data with structs and methods

type User struct {
	ID   int
	Name string
}

func (u User) Greeting() string {
	return "Hello, " + u.Name
}

Methods attach behavior to a type. Use pointer receivers when the method mutates the value or copying it would be undesirable.

Handle errors explicitly

user, err := loadUser(id)
if err != nil {
	return fmt.Errorf("load user %d: %w", id, err)
}

Errors are values. Return them, wrap them with context, and inspect known causes with errors.Is or errors.As. Reserve panics for unrecoverable programming errors.

Learn interfaces from the consumer

Interfaces describe behavior. Define small interfaces near the code that consumes them rather than creating large abstractions in advance.

type UserStore interface {
	Find(context.Context, int) (User, error)
}

Any type with that method satisfies the interface automatically.

Add concurrency deliberately

Goroutines run functions concurrently; channels communicate values; mutexes protect shared state. Concurrency is useful when work can overlap, not as a default replacement for straightforward sequential code.

Continue with goroutines, channels, WaitGroup, and mutexes.

Build and test an HTTP handler

func health(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	io.WriteString(w, `{"ok":true}`)
}

Register the handler with a ServeMux, then test it using httptest. The HTTP server tutorial and REST API tutorial develop this into a complete service.

A practical learning order

  1. Write small command-line programs until functions, slices, maps, and structs feel normal.
  2. Learn error handling and package design.
  3. Write table-driven tests.
  4. Learn goroutines, channels, cancellation, and race detection.
  5. Build an HTTP service using the standard library.
  6. Add persistence, observability, and deployment only after the core service is correct.

The fastest route is repeated practice: read one concept, write a small program, test it, and use it in a larger project.