Chapter 61 — Building CLI Applications
Question
Given below is a code snippet that:
Reads command-line arguments.
Checks whether an argument was supplied.
Converts a string argument into an integer.
Handles invalid input.
Demonstrates a practical Go CLI pattern.
What should be the output of the following code?
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
if len(os.Args) < 2 {
fmt.Println("usage: app <number>")
return
}
number, err := strconv.Atoi(os.Args[1])
if err != nil {
fmt.Println("invalid number")
return
}
fmt.Println("double:", number*2)
}Assume the program is run as:
go run main.go 21Answer
double: 42Step-by-step explanation
os.Argscontains the command-line arguments.os.Args[0]is normally the program name.os.Args[1]is therefore"21".strconv.Atoiconverts"21"from a string to the integer21.errisnil, meaning conversion succeeded.21 * 2produces42.
How to read the important code
number, err := strconv.Atoi(os.Args[1])"number comma err colon equals strconv dot Atoi, open parenthesis, os dot Args square bracket one, close parenthesis."
Key takeaway
A Go CLI commonly reads arguments, validates them, converts them into useful types, and handles errors explicitly.
Chapter 62 — Working with External APIs
Question
Given below is a code snippet that:
Creates an HTTP client.
Sends a GET request to an external API.
Checks the HTTP status.
Decodes JSON into a Go struct.
Separates API communication from the data structure representing the response.
What should be the output of the following code?
package main
import (
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
)
type APIUser struct {
ID int `json:"id"`
Name string `json:"name"`
}
func fetchUser(client *http.Client, url string) (APIUser, error) {
resp, err := client.Get(url)
if err != nil {
return APIUser{}, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return APIUser{}, fmt.Errorf("unexpected status: %d", resp.StatusCode)
}
var user APIUser
if err := json.NewDecoder(resp.Body).Decode(&user); err != nil {
return APIUser{}, err
}
return user, nil
}
func main() {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, `{"id":7,"name":"Alice"}`)
}))
defer server.Close()
user, err := fetchUser(server.Client(), server.URL)
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(user.ID)
fmt.Println(user.Name)
}Answer
7
AliceStep-by-step explanation
httptest.NewServercreates a temporary HTTP server.The server returns JSON containing an ID and name.
fetchUsersends a GET request.defer resp.Body.Close()ensures the response body is closed after the function finishes.The status code is checked.
json.NewDecoderreads the JSON response directly intoAPIUser.The function returns the populated struct.
The program prints
7andAlice.
How to read the important code
if err := json.NewDecoder(resp.Body).Decode(&user); err != nil {"if err colon equals json dot NewDecoder, open parenthesis, resp dot Body, close parenthesis, dot Decode, open parenthesis, ampersand user, close parenthesis, semicolon, err is not equal to nil."
Key takeaway
When consuming an external API, handle transport errors, HTTP status errors, response cleanup, and JSON decoding separately.
Chapter 63 — Caching & Background Jobs
Question
Given below is a code snippet that:
Stores expensive results in an in-memory cache.
Returns the cached value on subsequent requests.
Uses a background goroutine to refresh data.
Demonstrates the basic idea behind caching and background work.
What should be the output of the following code?
package main
import (
"fmt"
"sync"
"time"
)
type Cache struct {
mu sync.Mutex
data map[string]string
}
func (c *Cache) Get(key string) (string, bool) {
c.mu.Lock()
defer c.mu.Unlock()
value, ok := c.data[key]
return value, ok
}
func (c *Cache) Set(key, value string) {
c.mu.Lock()
defer c.mu.Unlock()
c.data[key] = value
}
func main() {
cache := &Cache{data: make(map[string]string)}
go func() {
time.Sleep(20 * time.Millisecond)
cache.Set("weather", "sunny")
fmt.Println("background job: cache refreshed")
}()
cache.Set("weather", "cloudy")
fmt.Println("initial:", cacheValue(cache, "weather"))
time.Sleep(50 * time.Millisecond)
fmt.Println("after job:", cacheValue(cache, "weather"))
}
func cacheValue(cache *Cache, key string) string {
value, ok := cache.Get(key)
if !ok {
return "missing"
}
return value
}Answer
initial: cloudy
background job: cache refreshed
after job: sunnyStep-by-step explanation
The cache starts empty.
A background goroutine starts.
The main goroutine stores
"cloudy".The first lookup therefore returns
"cloudy".The background job waits 20 milliseconds.
It then replaces the value with
"sunny".The main goroutine waits 50 milliseconds, giving the background job enough time to run.
The second lookup therefore returns
"sunny".sync.Mutexprevents simultaneous access from corrupting the map.
How to read the important code
mu sync.Mutex"mu, type sync dot Mutex."
A mutex is a lock that allows only one goroutine at a time to enter protected code.
Key takeaway
Caching avoids repeated expensive work, while background jobs move work away from the main request path.
Chapter 64 — WebSockets & Real-Time Applications
Question
Given below is a code snippet that:
Demonstrates the core idea of a real-time connection.
Uses a simulated message channel to represent incoming messages.
Processes messages continuously.
Shows the pattern used by real-time applications.
What should be the output of the following code?
package main
import "fmt"
func main() {
messages := make(chan string)
go func() {
messages <- "connected"
messages <- "new message"
messages <- "disconnected"
close(messages)
}()
for message := range messages {
fmt.Println(message)
}
}Answer
connected
new message
disconnectedStep-by-step explanation
messagesis an unbuffered channel of strings.The goroutine sends
"connected".The main goroutine receives it through the
range.The process repeats for the next two messages.
close(messages)tells receivers that no more messages will arrive.The
rangeloop automatically stops after the channel is closed and emptied.
A real WebSocket application adds a network connection around this same general idea: messages can arrive continuously rather than through ordinary request/response HTTP calls.
How to read the important code
for message := range messages {"for message colon equals range messages, open curly brace."
Key takeaway
Real-time systems continuously receive and process events instead of waiting for a new HTTP request for every message.
Chapter 65 — Dockerizing Go Applications
Question
Given below is a code snippet that:
Shows a minimal Go application suitable for containerization.
Demonstrates that the application listens on a configurable port.
Uses an environment variable.
Illustrates the application behavior expected inside a Docker container.
What should be the output of the following code?
package main
import (
"fmt"
"os"
)
func main() {
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
fmt.Println("application listening on port", port)
}Assume the container is started with:
PORT=9000Answer
application listening on port 9000Step-by-step explanation
Containers should generally receive environment-specific configuration from outside the application.
os.Getenv("PORT")reads thePORTenvironment variable.The container supplies
9000.Therefore the application uses port
9000.If
PORTwere absent, the code would use8080.
A typical production Docker setup would compile the Go program into a binary and place that binary into a small runtime image.
How to read the important code
port := os.Getenv("PORT")"port colon equals os dot Getenv, open parenthesis, quote PORT quote, close parenthesis."
Key takeaway
A container should package the application consistently while environment variables provide environment-specific configuration.
Chapter 66 — Go in CI/CD
Question
Given below is a code snippet that:
Contains a function with a testable result.
Demonstrates the kind of code a CI pipeline can automatically test.
Shows how a failing test would indicate a broken build.
Represents the relationship between source code and automated quality checks.
What should be the output of the following code?
package main
import "fmt"
func Add(a, b int) int {
return a + b
}
func main() {
fmt.Println(Add(10, 20))
}Assume the CI pipeline performs:
go test ./...
go build ./...and the repository contains a test that checks:
Add(10, 20) == 30Answer
CI result:
tests passed
build passed
Program output:
30Step-by-step explanation
Addreturns the sum of two integers.The automated test checks whether
Add(10, 20)equals30.The test passes.
go build ./...verifies that the project can be compiled.Therefore the CI pipeline can mark this revision as successful.
CI means Continuous Integration: automatically checking changes as they are submitted.
CD commonly means Continuous Delivery/Deployment: automatically preparing or deploying validated software.
How to read the important code
go test ./..."go test dot slash dot dot dot."
./... means the current module and packages beneath it.
Key takeaway
CI/CD turns testing, building, and deployment checks into repeatable automated steps instead of relying entirely on manual checking.
Chapter 67 — Git & Go Development Workflow
Question
Given below is a code snippet that:
Represents a small change made during normal development.
Demonstrates a function that can be tested independently.
Shows the kind of change a developer would commit and push through Git.
Connects source-code changes with testing and collaboration.
What should be the output of the following code?
package main
import "fmt"
func IsAdult(age int) bool {
return age >= 18
}
func main() {
ages := []int{17, 18, 25}
for _, age := range ages {
fmt.Println(age, IsAdult(age))
}
}Answer
17 false
18 true
25 trueStep-by-step explanation
agescontains three test values.The
forloop processes each age.IsAdultreturnsfalsefor17.18 >= 18is true.25 >= 18is also true.In a real workflow, you might modify this function, run tests, inspect the change with Git, commit it, and push it for review.
A common workflow is:
edit → test → git diff → commit → push → CI → review → mergeHow to read the important code
for _, age := range ages {"for blank identifier comma age colon equals range ages, open curly brace."
The _ is the blank identifier. It means "I intentionally don't need this value."
Key takeaway
Professional Go development is not just writing code; it is writing, testing, reviewing, versioning, and integrating code safely.
Chapter 68 — Common Go Interview Questions
Question
Given below is a code snippet that:
Tests your understanding of slices.
Demonstrates that two slice variables can refer to the same underlying array.
Shows how mutation through one slice can affect another.
Tests an important Go interview concept.
What should be the output of the following code?
package main
import "fmt"
func main() {
numbers := []int{10, 20, 30}
a := numbers
b := numbers[:2]
b[0] = 99
fmt.Println(numbers)
fmt.Println(a)
fmt.Println(b)
}Answer
[99 20 30]
[99 20 30]
[99 20]Step-by-step explanation
numbersis a slice containing three elements.a := numberscreates another slice referring to the same underlying data.b := numbers[:2]creates a slice containing the first two elements.These slices share the same underlying array.
b[0] = 99changes the first element of that shared array.Therefore
numbers[0]anda[0]also become99.bcontains only the first two elements.
How to read the important code
b := numbers[:2]"b colon equals numbers, colon two, square bracket."
It means: create a slice from the beginning of numbers up to, but not including, index 2.
Key takeaway
A slice is a descriptor of an underlying array, so copying a slice does not necessarily copy its elements.
Chapter 69 — Go Coding Interview Problems
Question
Given below is a code snippet that:
Uses a map to detect duplicate values.
Demonstrates a common interview algorithm.
Processes the input only once.
Shows how a Go map can provide fast membership checking.
What should be the output of the following code?
package main
import "fmt"
func firstDuplicate(numbers []int) (int, bool) {
seen := make(map[int]bool)
for _, number := range numbers {
if seen[number] {
return number, true
}
seen[number] = true
}
return 0, false
}
func main() {
numbers := []int{4, 7, 2, 7, 9}
number, found := firstDuplicate(numbers)
fmt.Println(number)
fmt.Println(found)
}Answer
7
trueStep-by-step explanation
seenstarts as an empty map.4is not present, so it is added.7is not present, so it is added.2is not present, so it is added.The next
7is already in the map.The function immediately returns
7andtrue.It does not need to inspect
9.
How to read the important code
if seen[number] {"if seen square bracket number square bracket, open curly brace."
The map lookup returns the stored boolean value.
Key takeaway
A map can turn repeated membership checks into an efficient one-pass algorithm.
Chapter 70 — Go System Design Fundamentals
Question
Given below is a code snippet that:
Separates an HTTP handler from business logic.
Uses an interface between layers.
Demonstrates dependency injection.
Represents a simplified production service architecture.
Shows how system components can have clearly defined responsibilities.
What should be the output of the following code?
package main
import "fmt"
type UserStore interface {
FindName(id int) string
}
type Database struct{}
func (Database) FindName(id int) string {
return "Alice"
}
type UserService struct {
store UserStore
}
func (s UserService) GetUserName(id int) string {
return s.store.FindName(id)
}
type Handler struct {
service UserService
}
func (h Handler) Serve(id int) {
name := h.service.GetUserName(id)
fmt.Println("HTTP 200:", name)
}
func main() {
db := Database{}
service := UserService{store: db}
handler := Handler{service: service}
handler.Serve(42)
}Answer
HTTP 200: AliceStep-by-step explanation
DatabaseimplementsUserStore.UserServicedepends on theUserStoreinterface rather than directly depending on a concrete database.Handlerdepends onUserService.The request enters the handler.
The handler asks the service for the user.
The service asks the store.
The database returns
"Alice".The handler produces the response.
The architectural flow is:
HTTP Handler
↓
Service / Business Logic
↓
Repository / Data Access
↓
DatabaseHow to read the important code
type UserStore interface {
FindName(id int) string
}"type UserStore interface, open curly brace, FindName open parenthesis id int close parenthesis string, close curly brace."
Key takeaway
Good system design separates responsibilities and makes dependencies replaceable and testable.
Chapter 71 — Production Debugging Scenarios
Question
Given below is a code snippet that:
Demonstrates a common production bug involving shared state.
Uses a mutex to protect a shared counter.
Runs multiple goroutines concurrently.
Shows the correct result after synchronization.
What should be the output of the following code?
package main
import (
"fmt"
"sync"
)
func main() {
var mu sync.Mutex
counter := 0
var wg sync.WaitGroup
for i := 0; i < 1000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
mu.Lock()
counter++
mu.Unlock()
}()
}
wg.Wait()
fmt.Println(counter)
}Answer
1000Step-by-step explanation
counterstarts at0.The loop launches 1,000 goroutines.
Each goroutine must increment the same variable.
counter++is a read-modify-write operation.Without synchronization, multiple goroutines could interfere with one another, causing a race condition.
mu.Lock()allows only one goroutine at a time to modify the counter.mu.Unlock()releases the lock.WaitGroupensures the main goroutine waits for all 1,000 goroutines.Therefore the final value is
1000.
How to read the important code
mu.Lock()
counter++
mu.Unlock()"mu dot Lock, open parenthesis, close parenthesis; counter plus plus; mu dot Unlock, open parenthesis, close parenthesis."
Key takeaway
When multiple goroutines access shared mutable data, synchronization is often necessary to prevent race conditions.
Chapter 72 — Complete Job-Ready Go Project
Question
Given below is a code snippet that:
Combines HTTP handling, JSON, a service layer, an in-memory repository, error handling, and HTTP status codes.
Represents a miniature backend application.
Demonstrates how the concepts learned throughout the course fit together.
What should be the output of the following code?
package main
import (
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
}
type UserRepository struct {
users map[int]User
}
func (r UserRepository) Find(id int) (User, error) {
user, ok := r.users[id]
if !ok {
return User{}, fmt.Errorf("user not found")
}
return user, nil
}
type UserService struct {
repo UserRepository
}
func (s UserService) GetUser(id int) (User, error) {
return s.repo.Find(id)
}
func NewHandler(service UserService) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
user, err := service.GetUser(1)
if err != nil {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(user)
})
}
func main() {
repo := UserRepository{
users: map[int]User{
1: {ID: 1, Name: "Alice"},
},
}
service := UserService{repo: repo}
handler := NewHandler(service)
req := httptest.NewRequest(http.MethodGet, "/users/1", nil)
rec := httptest.NewRecorder()
handler.ServeHTTP(rec, req)
fmt.Println(rec.Code)
fmt.Print(rec.Body.String())
}Answer
200
{"id":1,"name":"Alice"}Step-by-step explanation
The repository contains Alice.
The service depends on the repository.
NewHandlerreceives the service.A fake HTTP request is created.
The handler asks the service for user
1.The repository finds Alice.
The handler sets the response content type.
json.NewEncoderconverts Alice into JSON.The default successful HTTP status is
200.The response body contains Alice's JSON representation.
How to read the important code
handler := NewHandler(service)"handler colon equals NewHandler, open parenthesis, service, close parenthesis."
This creates the HTTP handler while injecting the service it needs.
Key takeaway
A job-ready Go project combines small understandable components into a complete, testable application rather than putting everything in one giant function.
Chapter 73 — Advanced Go Patterns
Question
Given below is a code snippet that:
Demonstrates a generic function.
Works with different numeric types.
Uses a type constraint.
Shows how generics can eliminate duplicated functions while retaining compile-time type checking.
What should be the output of the following code?
package main
import "fmt"
type Number interface {
int | float64
}
func Sum[T Number](values []T) T {
var total T
for _, value := range values {
total += value
}
return total
}
func main() {
fmt.Println(Sum([]int{10, 20, 30}))
fmt.Println(Sum([]float64{1.5, 2.5}))
}Answer
60
4Step-by-step explanation
Numberis a type constraint.It says that
Tcan be eitherintorfloat64.Sum[T Number]is a generic function.Trepresents a type chosen when the function is used.The first call uses
int.The second call uses
float64.The same function therefore works with both types.
The first sum is
60.The second sum is
4.
How to read the important code
func Sum[T Number](values []T) T"func Sum, square bracket T Number, square bracket, open parenthesis, values square bracket T, close parenthesis, T."
The T is a type parameter. It allows the function to operate on different types.
Key takeaway
Generics let you write reusable, type-safe code that works with multiple types.
Chapter 74 — Go Performance & Scalability
Question
Given below is a code snippet that:
Demonstrates the effect of preallocating slice capacity.
Uses
maketo allocate a slice with known capacity.Avoids repeated growth of the underlying array in this example.
Introduces an important performance optimization without changing the result.
What should be the output of the following code?
package main
import "fmt"
func buildNumbers() []int {
numbers := make([]int, 0, 5)
for i := 1; i <= 5; i++ {
numbers = append(numbers, i)
}
return numbers
}
func main() {
numbers := buildNumbers()
fmt.Println(numbers)
fmt.Println(len(numbers))
fmt.Println(cap(numbers))
}Answer
[1 2 3 4 5]
5
5Step-by-step explanation
make([]int, 0, 5)creates an integer slice with length0and capacity5.Length means the number of elements currently in the slice.
Capacity means how many elements the underlying storage can hold before it needs to grow.
Five numbers are appended.
The final length becomes
5.Because the initial capacity was already
5, the slice has enough capacity for all five elements.Therefore the final capacity is
5.
Preallocation can improve performance when you know approximately how many elements you will need because it can reduce unnecessary allocations and copying.
How to read the important code
numbers := make([]int, 0, 5)"numbers colon equals make, open parenthesis, square bracket int, zero, comma, five, close parenthesis."
This creates a slice of int with length 0 and capacity 5.
Key takeaway
Performance optimization in Go often starts with reducing unnecessary allocations, copying, blocking, and work—not with clever code.
Chapter 75 — Final Job-Level Go Mastery & Interview Preparation
Question
Given below is a code snippet that:
Combines interfaces, dependency injection, error handling, concurrency, synchronization, and HTTP-style application logic.
Represents the type of integrated thinking expected from a professional Go developer.
Uses a worker goroutine to process a job.
Demonstrates the complete flow from input to result.
What should be the output of the following code?
package main
import (
"errors"
"fmt"
"sync"
)
type Repository interface {
Find(id int) (string, error)
}
type MemoryRepository struct {
data map[int]string
}
func (r MemoryRepository) Find(id int) (string, error) {
name, ok := r.data[id]
if !ok {
return "", errors.New("user not found")
}
return name, nil
}
type Service struct {
repo Repository
}
func (s Service) Process(id int) (string, error) {
name, err := s.repo.Find(id)
if err != nil {
return "", err
}
return "Welcome, " + name, nil
}
func main() {
repo := MemoryRepository{
data: map[int]string{
1: "Alice",
},
}
service := Service{repo: repo}
jobs := make(chan int)
results := make(chan string)
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
for id := range jobs {
message, err := service.Process(id)
if err != nil {
results <- "error: " + err.Error()
continue
}
results <- message
}
}()
go func() {
jobs <- 1
close(jobs)
wg.Wait()
close(results)
}()
for result := range results {
fmt.Println(result)
}
}Answer
Welcome, AliceStep-by-step explanation
MemoryRepositoryimplements theRepositoryinterface.Servicedepends on the interface rather than directly depending on the concrete repository.A
jobschannel carries user IDs to the worker.A
resultschannel carries processed results back.A worker goroutine receives job
1.The service asks the repository for user
1.The repository returns
"Alice".The service creates
"Welcome, Alice".The worker sends that result through the
resultschannel.The main goroutine receives it and prints it.
The job channel is closed after the job is sent.
The worker finishes.
The
WaitGroupensures the worker has finished beforeresultsis closed.The results loop then finishes safely.
How to read the important code
for result := range results {"for result colon equals range results, open curly brace."
This means:
Keep receiving results from the channel until the channel is closed.
Key takeaway
Job-ready Go means being able to combine fundamentals—interfaces, errors, concurrency, synchronization, APIs, testing, databases, and clean architecture—into reliable software.