70 questions / 10 random questions
Random questions, instant feedback, and review for missed questions.
Code assumed a slice always kept the same backing array after append. What is the correct understanding?
Answer: It may allocate a new backing array when capacity is insufficient
A slice is a view with pointer, length, and capacity. Always retain append's return value because it may reference a newly allocated array.
How should code distinguish an absent map key from a stored zero value?
Answer: Use the two-value form value, ok := m[key]
The comma-ok idiom reports key presence. A missing key still yields the element type's zero value, so the value alone is insufficient.
An external package type should satisfy a local interface. What is required in Go?
Answer: It satisfies the interface implicitly through its method set
Interface implementation is implicit. A consumer can define a minimal interface, and any type with the matching method set satisfies it.
A method must modify a struct's state. Which receiver is appropriate?
Answer: A pointer receiver
A pointer receiver can mutate the original value and avoid copying a large struct. Keep receiver choices consistent across the type's methods.
You need to add operation context while preserving sentinel-error checks. What is appropriate?
Answer: Wrap with %w and check with errors.Is
Using %w preserves the error chain, allowing added context while callers inspect causes with errors.Is or errors.As.
A function has multiple early returns after opening a file. How should it avoid leaking the file?
Answer: Defer Close immediately after a successful open
Registering defer immediately after acquisition closes the resource on later return paths. Handle close errors explicitly when they matter.
A library panics on ordinary input-validation failure. What is the preferred API improvement?
Answer: Return expected failures as error values
Panic is for unrecoverable invariant violations. Invalid input and external I/O failures should be returned as errors callers can handle.
An outbound API call must follow request cancellation and deadlines. What design is appropriate?
Answer: Accept the caller's Context as the first argument and attach it to the request
Propagate context through the call chain into HTTP and database operations. The creator of a cancel function should defer its call.
When a pipeline consumer exits early, producer goroutines block forever on channel sends. What should be improved?
Answer: Select on Done and send, propagating cancellation to every stage
Each stage should observe cancellation and be able to leave blocked sends or receives, preventing goroutine leaks.
Who should normally close a job channel shared by multiple workers?
Answer: The sending owner that knows all sends are done
The sending owner that knows all sends are finished should close the channel. Receiver-side closure can cause concurrent senders to panic.
When does a send on an unbuffered channel complete?
Answer: When a corresponding receiver is ready
An unbuffered channel creates a rendezvous: send and receive block until both sides are ready, combining communication with synchronization.
A select with default caused a loop to consume a full CPU core. What explains and improves it?
Answer: default runs without waiting, so design blocking or a timer
When no case is ready, default runs immediately and can busy-loop. Remove default when waiting is intended or use an appropriate timer.
Many jobs need concurrency without creating one goroutine per input and exhausting memory. What is appropriate?
Answer: A bounded pool of fixed workers reading a job channel
Bound concurrency with worker count and design queueing and backpressure. Add context cancellation, error collection, and completion waiting.
Multiple goroutines read and write the same map. How should it be protected?
Answer: Confine ownership to one goroutine or synchronize with a mutex
Concurrent reads and writes on a regular map are unsafe. Choose ownership confinement, a mutex, or sync.Map when its specialized use case fits.
Which command should CI use to detect data races in exercised code?
Answer: go test -race ./...
The race detector instruments executed memory accesses. Run it with tests and integration workloads that exercise concurrent paths.
You need to close a results channel only after several goroutines finish. What is appropriate?
Answer: Count completion with WaitGroup and close after Wait
Call Add before launch, defer Done in each worker, and have one coordinator close after Wait to prevent double close and send-after-close.
Expensive client initialization may be requested concurrently but must run once. What should be used?
Answer: sync.Once
sync.Once.Do executes a function once even under concurrent calls and synchronizes visibility of initialization results.
Several fields must be updated as one consistent state. Is a single atomic counter sufficient?
Answer: Use a mutex or publish immutable snapshots for compound invariants
Atomics work for individual values but do not automatically preserve invariants across fields. Synchronize a critical section or publish whole snapshots.
An outbound HTTP API can hang and accumulate goroutines. What is the baseline improvement?
Answer: Reuse a Client with timeouts and propagate the context
Reuse clients and transports and set connection, header, and overall deadlines. Close response bodies and bound retries with backoff.
When an inbound HTTP request disconnects, a downstream database query should stop. What is appropriate?
Answer: Pass r.Context() to QueryContext
An http.Request context is canceled on client disconnect or request completion. Passing it to context-aware APIs stops unnecessary downstream work.
Which baseline configuration helps protect a public HTTP server from slow clients such as Slowloris?
Answer: Configure server timeouts such as ReadHeaderTimeout
Tune ReadHeaderTimeout, ReadTimeout, WriteTimeout, and IdleTimeout to traffic characteristics and align them with reverse-proxy limits.
How should a Go HTTP server shut down safely when Kubernetes sends a termination signal?
Answer: Receive a signal context and call Shutdown with a deadline
Stop accepting new work, allow in-flight requests a bounded grace period, and define forced termination after the deadline; fail readiness first.
A JSON API must separate Go field names from wire names and omit empty values. What should be used?
Answer: Add a json tag with omitempty to an exported field
encoding/json processes exported fields, with struct tags controlling wire names and omitempty. Understand each type's empty-value semantics.
Configuration JSON typos must fail as unknown fields instead of being silently ignored. What is appropriate?
Answer: Enable DisallowUnknownFields on the Decoder
For strict configuration loading, use DisallowUnknownFields and separately validate required values and ranges after decoding.
How should database/sql execute a query containing user input safely?
Answer: Use placeholders and bound arguments
Bind values using the driver's placeholder syntax and allowlist dynamic identifiers. String concatenation creates SQL injection risk.
Several SQL updates must run in a transaction and reliably roll back on errors. What is the usual pattern?
Answer: Defer Rollback after BeginTx and Commit only on success
A deferred tx.Rollback covers early returns and is harmless after a successful commit. Use tx methods throughout the transaction.
A multi-gigabyte upload must be processed without loading it all into memory. Which abstraction fits?
Answer: Stream from io.Reader and use io.Copy where needed
io.Reader and Writer enable chunked streaming. Also enforce size limits and handle cancellation and partial-write errors.
bufio.Scanner stopped on an unusually long line. What should be done?
Answer: Set Scanner.Buffer limits or use bufio.Reader and check Err
Scanner has a token-size limit. Set a justified bound rather than making untrusted input unlimited, and handle Err after scanning.
Many input and expected-output cases must test one function readably. What is appropriate?
Answer: Use a table-driven test with named t.Run subtests
A table of names, inputs, and expectations makes cases easy to add and failures easy to locate. Watch shared state when parallelizing.
How should an HTTP handler be unit-tested without opening a real port?
Answer: Use httptest.NewRequest and NewRecorder
httptest request and recorder call handlers directly and verify status, headers, and body. Use httptest.Server for client integration.
You need to compare execution time and allocations before and after an optimization. What is appropriate?
Answer: Use testing.B benchmarks with -benchmem
Go benchmarks adapt iteration counts and report time and allocations per operation. Run repeatedly in a stable environment and compare statistically.
You want unexpected parser inputs to reveal crashes or invariant violations. What should be used?
Answer: Define a fuzz test with seed corpus and invariants
Fuzzing mutates seed inputs and minimizes and stores crashing cases. It is useful for parsers at security boundaries.
Which command reconciles go.mod and go.sum after imports change?
Answer: go mod tidy
go mod tidy adds required module requirements and checksums and removes unnecessary ones. CI can verify that it leaves no diff.
What is the primary role of go.sum?
Answer: Record module content checksums for verification
go.sum records hashes for module versions and go.mod content, helping detect tampering or mismatches. It is normally committed.
A package should be importable only from within its repository subtree. What should be used?
Answer: Place it under an internal directory
The Go toolchain enforces import visibility for internal directories, avoiding accidental public API commitments.
A go.work file supports local development across modules. What should CI be careful about?
Answer: Control GOWORK and test modules independently so CI does not rely on the local workspace
go.work is useful but may make CI select local modules instead of released dependency versions. Verify each module independently.
Which Go-specific tool checks whether known dependency vulnerabilities are reachable from your code?
Answer: govulncheck ./...
govulncheck combines the Go vulnerability database with call-graph analysis to report known vulnerabilities affecting reachable code.
You need to investigate CPU hotspots and allocation sources under production-like load. What is appropriate?
Answer: Capture profiles with pprof and analyze with go tool pprof
Capture CPU, heap, and goroutine profiles over representative windows and inspect top entries or flame graphs. Restrict profiling endpoints.
Logs in a distributed system must be searchable and correlate requests. What is an appropriate Go service logging design?
Answer: Use slog to structure level, request ID, operation, and error
Structured logging enables field-based filtering and aggregation. Propagate trace or request IDs and redact credentials and personal data.
Which combination appropriately ships a small Go service container and handles termination signals?
Answer: Build a minimal multi-stage image and shut down via NotifyContext
Separate the build toolchain from runtime, include only required CA or timezone data, and perform bounded graceful shutdown from a signal context.
A nil *MyError was assigned to an error interface, and err != nil became true. What is the key explanation?
Answer: An interface is a type-value pair, so a typed nil is not nil
An interface is nil only when both its dynamic type and value are nil. Avoid returning a typed nil and return a literal nil error on success.
A struct containing sync.Mutex was copied after the lock had been used, causing inconsistent behavior. What is the proper fix?
Answer: Handle lock-holding values by pointer and check go vet copylocks
Synchronization primitives such as Mutex must not be copied after first use. Use pointer ownership and inspect value parameters, returns, and assignments.
You maintain concurrent closures over range variables in a module with an older go directive. What is a safe migration approach?
Answer: Check the go version and tests, capture iteration values explicitly, then upgrade
Per-iteration loop variable semantics changed in Go 1.22 and depend on the module's go version. Use go vet and concurrent tests, and pass intended values explicitly during migration.
A loop defers file.Close for many files, retaining descriptors until the outer function returns. What is the proper fix?
Answer: Split one item into a small function and defer Close there
A defer runs when its enclosing function returns. An iteration-scoped helper releases each file promptly while preserving cleanup on early returns.
You are considering sync.Pool to reduce temporary buffer allocations on a hot path. Which use is appropriate?
Answer: Pool disposable temporaries and reset them when acquired
Items in sync.Pool may disappear at any time, so it is not a cache or ownership store. Measure allocation impact and reset lengths, references, and sensitive data.
On Go 1.25 or later, you want concise code to start several independent tasks and wait for all of them. What is appropriate?
Answer: Use WaitGroup.Go and Wait, designing error propagation separately
WaitGroup.Go combines the common Add, goroutine launch, and Done pattern. Use result channels or errgroup when errors and cancellation are required.
Parallel downstream API calls should cancel sibling work on the first error and wait for all tasks. Which design is appropriate?
Answer: Share a context via errgroup.WithContext and return Wait's error
errgroup coordinates errors, cancellation, and waiting for related tasks. Pass its context downstream so blocked operations can actually stop.
A library stores a request trace ID in context. How should it avoid key collisions?
Answer: Use an unexported key type and store only request-scoped values
A distinct key type prevents collisions with other packages. Context is for deadlines, cancellation, and request-scoped values, not hidden required parameters or long-lived configuration.
Creating a new http.Client and Transport for every request increased connection counts and latency. What is the basic improvement?
Answer: Reuse a configured Client and Transport with explicit timeouts and limits
http.Client and Transport are designed for concurrent reuse. Connection pooling avoids repeated handshakes; tune idle, per-host, and timeout limits for the workload.
A client reads only part of an external HTTP response body before returning, and connection reuse is unreliable. What is required?
Answer: Always close the body and drain it within a safe bound when reusing
The caller owns closing a client response body. Do not drain huge or endless bodies without bounds; combine size limits and request cancellation.
A huge JSON request body caused memory pressure through io.ReadAll. What is the core handler-side control?
Answer: Enforce a read limit with MaxBytesReader and return a client error on overflow
Limit actual bytes read on the server rather than trusting client metadata. Add streaming decode, field validation, timeouts, and rate limits as defense in depth.
A Go API behind a reverse proxy directly trusts X-Forwarded-For for audit logs and rate limits. What is a safe design?
Answer: Define trusted proxy boundaries and use only headers normalized by them
Direct clients can spoof forwarding headers. Verify the peer is a trusted proxy, strip and reset external headers there, then interpret the hop chain.
Under increased traffic, database/sql opened enough connections to hit the database limit. What pool design should be applied first?
Answer: Bound MaxOpenConns from database capacity and measure wait statistics
sql.DB is a connection pool. Budget aggregate connections across replicas and use DBStats such as WaitCount and WaitDuration to distinguish saturation from query latency.
Scanning a nullable SQL timestamp into time.Time fails only for NULL rows. What is the appropriate modeling?
Answer: Scan into sql.NullTime and map Valid to the domain's optional value
Database NULL and Go zero values have different meanings. Represent nullability at the persistence boundary and map it to a domain pointer or optional type.
A generic function should accept user-defined integer types as well as the predeclared type. Which constraint is appropriate?
Answer: Include an underlying-type term such as ~int in the constraint
~T includes defined types whose underlying type is T. Constrain only the operations the implementation needs instead of relying on broad any and reflection.
You must prevent internal module paths from being sent to public proxies or checksum databases and fetch them privately. What is appropriate?
Answer: Set the prefix in GOPRIVATE and use authenticated VCS or a private proxy
GOPRIVATE marks matching modules private and supplies defaults for GONOPROXY and GONOSUMDB. Keep public checksum verification and manage credentials separately.
Developers and CI select different Go toolchains, producing inconsistent builds. What improves reproducibility?
Answer: Declare the go requirement and toolchain policy, then pin and verify CI images
The go directive affects language and module behavior, and toolchain selection is a build input. Track security patch releases and test upgrades consistently before rollout.
A test of timeouts and goroutine coordination relies on sleeps and is slow and flaky. What is effective on Go 1.25 or later?
Answer: Run in testing/synctest and use Wait to synchronize blocked goroutines
testing/synctest isolates test goroutines and virtual time, enabling waiting-condition tests without real sleeps. Fake external I/O or cover it in integration tests.
On Go 1.24 or later, which benchmark form reduces setup timing mistakes and dead-code elimination while making the measured loop explicit?
Answer: Run under for b.Loop() after setup and control the timer for per-iteration setup
B.Loop excludes outer setup and cleanup from timing and helps prevent inappropriate elimination of work inside the loop. Control timing explicitly for required per-iteration preparation.
You want to optimize a Go binary using CPU profiles from production workloads. What is an appropriate PGO rollout?
Answer: Collect representative CPU profiles, build with default.pgo, and validate with canaries
Go PGO uses representative CPU profiles as compiler input for hot-path optimization. Continuously monitor workload representativeness, profile freshness, build reproducibility, performance, and binary-size regressions.
A request handler declares var counts map[string]int. Reading counts["ok"] works, but counts["ok"]++ panics. What explains this and fixes it?
Answer: A nil map permits reads but not writes; initialize it with make.
A map declared without initialization is nil. A missing-key read returns the element type's zero value, but a write panics. Initialize it with make(map[string]int) or a map literal before incrementing. This requirement is independent of concurrent access.
One goroutine selects between two input channels and cancellation. After one input finishes, it must keep waiting for the other. How can it disable only the finished input case?
Answer: Set that local channel variable to nil and continue selecting.
A receive from a nil channel cannot proceed, so its select case is disabled. Setting the receiver's local channel variable to nil after detecting closure leaves other input and cancellation cases active. Keep that variable owned by the selecting goroutine.
An int channel carries counts, including valid zero counts, and is closed by its sender. How should the receiver distinguish a valid zero from closure after the buffer is drained?
Answer: Use the two-value receive and treat ok being false as completion.
In v, ok := <-ch, ok is true for values sent before closure, including buffered zero values. Once the closed channel is drained, receives return the element's zero value and false. Test ok rather than the count.
defer logDuration(time.Since(start)) logs almost zero even for a long operation. logDuration only records its Duration argument. Which change measures elapsed time at function exit?
Answer: Defer a closure that calls time.Since when the closure actually runs.
Deferred call arguments are evaluated when the defer statement executes. With defer func() { logDuration(time.Since(start)) }(), time.Since runs at exit instead. Record start before the operation and leave it unchanged.
A *ValidationError is wrapped with fmt.Errorf and %w. How should a caller retrieve the original error's Field value?
Answer: Declare a target pointer and use errors.As to inspect the error chain.
Use var ve *ValidationError; if errors.As(err, &ve) { ... } to search wrapped errors and assign a match to ve. A direct type assertion checks only the outer error. Access Field only in the successful As branch.
A database/sql report checks every rows.Scan error, but treats rows.Next returning false after a connection failure as success. What additional check is needed?
Answer: After the loop, check rows.Err before declaring the report successful.
Next can return false on an iteration error as well as at the end. In addition to checking Scan, inspect rows.Err after iteration so a partial aggregate is not published as a complete report.
An external API returns HTTP 503, but a Go caller records success because client.Do returned nil err. The API defines only 2xx as success. What should change?
Answer: Check StatusCode for a 2xx response as well as checking the transport error.
client.Do does not return an error merely because a response is non-2xx. After checking err, evaluate StatusCode against the API contract. Retry decisions for 503 also need idempotency and backoff considerations, and the response Body must be closed.
Decoding JSON numeric ID 9007199254740993 into map[string]any rounds its value. Using the standard encoding/json Decoder, how can an ID within int64 range be preserved?
Answer: Enable UseNumber and parse with json.Number.Int64, checking the error.
JSON numbers decoded into any normally become float64, which cannot exactly represent this ID. Call UseNumber before Decode to retain json.Number, then check the value and error from Int64. Converting an already rounded float cannot restore lost digits.
Two time.Time values represent the same instant in UTC and Japan time. Which comparison checks instant equality despite their different display locations?
Answer: Use t.Equal(u) to test whether both represent the same instant.
Equal compares represented instants. The == operator also compares Location and monotonic clock information, so it can reject equal instants. Comparing formatted strings or only hours does not correctly account for zones and dates.
A test writes map[string]int entries as lines using for range. Identical contents sometimes produce a different order. How should output be stabilized in lexicographic key order?
Answer: Collect keys in a slice, sort them, then read values in that order.
Go does not specify map iteration order or guarantee that it repeats. Collect keys into a []string, sort them with sort.Strings, then look up each value in that order. This assumes the map is not modified during the process.