Go (Golang) is a statically-typed, compiled language developed by Google, known for simplicity, fast compilation, built-in concurrency via goroutines and channels, and strong standard library. These questions cover core language features, concurrency, memory management, and idiomatic Go patterns commonly tested in technical interviews.
Go is statically typed and compiled to native machine code, making it much faster than Python. Unlike Java, Go has no classes or inheritance; it uses structs and interfaces for composition, and goroutines/channels replace threads for concurrency.
A goroutine is a lightweight, cooperatively-scheduled unit of execution managed by the Go runtime, not the OS. Goroutines start with only ~2KB of stack (which grows dynamically) and thousands can run concurrently, whereas OS threads typically use ~1MB of stack and are more expensive to create and context-switch.
Every type in Go has a zero value—integers default to 0, booleans to false, strings to "", pointers/slices/maps/channels to nil. This eliminates undefined behavior from uninitialized variables and allows safe usage without explicit initialization.
An array has a fixed size defined at compile time and is a value type (copied on assignment). A slice is a dynamic, reference-type view over an underlying array with a length and capacity, and it is passed by reference semantics, making it far more commonly used.
new(T) allocates zeroed memory for type T and returns a *T pointer. make() is used only for slices, maps, and channels to initialize their internal data structures and returns the type itself (not a pointer), ready for use.
An interface in Go defines a set of method signatures. A type satisfies an interface implicitly by implementing all its methods—there is no explicit 'implements' keyword. This promotes loose coupling and makes testing with mocks straightforward.
defer schedules a function call to execute just before the surrounding function returns, regardless of how it returns (normally or via panic). It is commonly used for cleanup tasks like closing files, releasing locks, or logging, ensuring resources are freed even when errors occur.
A channel is a typed conduit for communicating between goroutines safely. An unbuffered channel (make(chan T)) blocks the sender until a receiver is ready and vice versa, providing synchronization. A buffered channel (make(chan T, n)) allows up to n values to be queued before blocking the sender.
A race condition occurs when two goroutines access shared memory concurrently and at least one access is a write without synchronization. Go provides the -race flag (go run -race or go test -race) to detect races at runtime, and they are prevented using sync.Mutex, sync.RWMutex, or channels.
select lets a goroutine wait on multiple channel operations simultaneously, executing whichever case is ready first. If multiple cases are ready, one is chosen at random. A default case makes select non-blocking, executing immediately if no channel is ready.
A value receiver operates on a copy of the struct, so mutations do not affect the original. A pointer receiver operates on the actual struct, allowing mutation and avoiding the cost of copying large structs. A type satisfies an interface with pointer receivers only when the variable is addressable (pointer type).
Go treats errors as values using the built-in error interface; functions typically return (result, error) and callers check the error explicitly. Best practices include wrapping errors with fmt.Errorf("context: %w", err) for context, using errors.Is/errors.As for inspection, and avoiding panic except for truly unrecoverable situations.
context.Context carries deadlines, cancellation signals, and request-scoped values across API boundaries and goroutines. It is critical for cancelling long-running operations (HTTP requests, DB queries) gracefully, preventing goroutine leaks, and propagating timeouts in microservices.
sync.WaitGroup is used to wait for a collection of goroutines to finish. You call wg.Add(n) before launching goroutines, each goroutine calls wg.Done() when it completes, and the main goroutine blocks on wg.Wait() until the counter reaches zero.
Escape analysis is performed by the Go compiler to determine whether a variable should be allocated on the stack or the heap. Variables that do not escape the function scope are stack-allocated (cheap, no GC pressure); those that escape (e.g., returned pointers) are heap-allocated and managed by the garbage collector.
Go uses a concurrent, tri-color mark-and-sweep GC that runs mostly in parallel with the application to minimize stop-the-world pauses. To minimize GC pressure, reduce heap allocations by reusing objects with sync.Pool, prefer stack-allocated values, avoid unnecessary interface boxing, and tune GOGC to control GC frequency.
Functional options is a pattern where a constructor accepts variadic functions (type Option func(*Config)) that modify a configuration struct, providing a flexible, extensible, and backward-compatible API without breaking changes. It avoids large parameter lists and makes optional settings explicit and self-documenting.
Go modules (introduced in Go 1.11) are the standard dependency management system. go.mod defines the module path and its direct dependencies with versions, while go.sum contains cryptographic checksums of all dependency content to ensure reproducible and tamper-proof builds. Commands like go get, go mod tidy, and go mod vendor manage the dependency graph.
sync.Mutex provides exclusive locking—only one goroutine can hold it at a time for either reading or writing. sync.RWMutex allows multiple concurrent readers (RLock) but only one writer (Lock) at a time. Use RWMutex when reads vastly outnumber writes to improve throughput on read-heavy workloads.
Create a fixed number of goroutines (workers) that each read from a shared jobs channel, process tasks, and optionally send results to a results channel. The main goroutine sends work into the jobs channel and closes it when done, causing workers to exit their range loops. A sync.WaitGroup ensures all workers finish before the program exits.
© RM Full Stack & AI Engineer · All interview questions · Roadmaps · Open the app