Interview Questions & Answers
Comprehensive questions covering Go, CLI, System Design, Algorithms, and Cloud.
A. Go Language Basics
Go (Golang) is an open-source, statically typed, compiled programming language created at Google.
Used for: High-performance backend services, Cloud-native applications, Microservices, Concurrency-heavy systems, CLI tools, DevOps tools.
Why popular: Extremely fast compilation, Built-in concurrency (goroutines & channels), Simple syntax, No inheritance complexity, Excellent standard library.
Tip: Go is ideal for distributed systems and scalable cloud architecture.
Using:
- Goroutines: Lightweight threads managed by Go runtime.
- Channels: Safe communication pipes between goroutines.
- sync.WaitGroup: Waiting for a collection of goroutines to finish.
- sync.Mutex: Locking mechanisms for shared data.
go func() {
fmt.Println("Running in goroutine")
}()
Go uses explicit error return values, not exceptions.
val, err := someFunc()
if err != nil {
return err
}
Advanced: Use fmt.Errorf() with %w for wrapping, and errors.Is()/errors.As() for checking types.
Interfaces are implicitly implemented. If a type provides the methods derived in the interface, it implements it (Duck Typing).
type Animal interface {
Speak() string
}
// Dog implicitly implements Animal by having Speak()
func (Dog) Speak() string { return "Woof" }
- Use goroutines for parallel execution.
- Avoid unnecessary memory allocations (use pointers for large structs).
- Use
sync.Poolfor object reuse to relieve GC pressure. - Prefer slices over arrays.
- Minimize locking scope or prefer atomic operations.
- Use buffered I/O.
Tools: go test -bench ., pprof (profiling), go build -gcflags "-m" (escape analysis).
- Automatically executed before
main(). - Used for package-level setup, initialization, or configuration.
- Cannot be called manually.
- A file/package can have multiple init functions.
Static: Explicit type declaration.
var age int = 10
Dynamic (Inference): Type inferred from value.
age := 10
B. Go Input / CLI Handling
Using fmt.Scan (space-separated) or bufio (buffered IO).
var name string
var age int
fmt.Scan(&name, &age)
Check values immediately after reading.
if age < 0 {
fmt.Println("Invalid age")
}
for {
fmt.Print("Enter age: ")
fmt.Scan(&age)
if age > 0 { break }
}
Use os.Args for raw arguments, flag for parsing flags, or libraries like Cobra/Viper for robust tools.
name := flag.String("name", "Guest", "User name")
flag.Parse()
fmt.Println("Hello", *name)
C. Code Explanations
VS Code's Go extension auto-generates the package name based on the folder name you opened. If you opened a folder named golangtestprojects, it assumes that is the package.
reader := bufio.NewReader(os.Stdin)
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
Explanation:
- Creates a buffered reader connected to Standard Input.
- Reads input bytes until it hits a newline character (Enter key).
strings.TrimSpaceremoves the trailing newline and any surrounding whitespace.
Common Mistake: Checking or writing to the wrong filename definition (e.g., user.json vs users.json).
D. Go CLI Features
The flag package parses command-line arguments like --port=8080.
port := flag.String("port", "8000", "Server port")
flag.Parse()
fmt.Printf("Starting on %s\n", *port)
Cobra is the standard for modern Go CLIs (used by Kubernetes, Docker). It manages commands, subcommands, and flags.
Viper handles configuration management (JSON/YAML files, env vars).
Enhance UX using libraries:
github.com/fatih/color:color.Red("Error!")github.com/briandowns/spinner: Show activity during long tasks.
Use json.MarshalIndent for pretty-printing data to storage.
data, _ := json.MarshalIndent(users, "", " ")
os.WriteFile("users.json", data, 0644)
Flow: Read File -> Unmarshal to Struct Slice -> Modify Slice (Append/Delete) -> Marshal -> Write Back.
Use the database driver to connect.
import _ "github.com/go-sql-driver/mysql"
db, _ := sql.Open("mysql", "user:pass@/dbname")
State management in CLI: Variables hold the "logged in" state (token/user struct). The main loop renders different options based on this state.
Run background tasks without blocking the UI/Input loop.
go func() {
performBackgroundSync()
}()
// Main CLI loop continues here...
E. Data Structures & Algorithms
Problem: Given nums[] and k, find number of contiguous subarrays having product less than k.
Algorithm: Sliding Window. Expand right pointer, multiply product. If product >= k, shrink left pointer until valid. Add right - left + 1 to count.
- Product of positive numbers increases as window expands.
- If a window [left, right] is valid, then all subarrays ending at right within that window are also valid.
- This reduces complexity from O(N³) to O(N).
F. Go Advanced Questions
Goroutine: Managed by Go runtime, starts with small stack (2KB), grows dynamically, multiplexed onto OS threads.
Thread: Managed by OS, fixed large stack (1MB+), expensive context switch.
Typed conduits for synchronization and data transfer between goroutines.
ch := make(chan int)
go func() { ch <- 10 }() // Send
val := <-ch // Receive
Unbuffered: make(chan int). Synchronous. Sender blocks until Receiver performs receive.
Buffered: make(chan int, 3). Asynchronous until buffer is full. Sender only blocks if buffer is full.
Like a switch for channels. Blocks until one of its cases (send/receive) can proceed. Used for handling timeouts or multiple data sources.
It uses a concurrent, tri-color mark-and-sweep algorithm. It is optimized for low latency (short stop-the-world pauses) rather than raw throughput.
Array: Fixed length, value type (copying copies entire array).
Slice: Dynamic length, reference type (pointer to underlying array).
Maps are not safe for concurrent use. Use sync.Mutex to lock before access, or use sync.Map for specific high-concurrency read-heavy cases.
Go favors Composition. Embedding a struct allows utilizing its methods, but it's not "is-a" relationship, it's "has-a" with syntax sugar.
type Car struct { Engine } // Car promotes methods of Engine
go mod init creates a new module. go.mod tracks dependencies and versions, replacing the old GOPATH system.
Schedules a function call to be run after the surrounding function returns. Executed in LIFO order. Common for cleanup (closing files, unlocking mutexes).
Panic: Stops normal execution, unwinds stack, runs deferred functions. Used for unrecoverable errors.
Recover: Regains control of a panicking goroutine. Only works inside defer.
The CPU reads data in word-sized chunks. Go struct fields are aligned to these boundaries. Proper ordering of struct fields (largest to smallest) can save memory by reducing padding.
Used to carry deadlines, cancellation signals, and request-scoped values across API boundaries and between processes.
Advanced: Golang & Concurrency
Determines if variables should be on stack or heap. Heap allocation causes GC pressure. Optimization: Keep variables on stack (don't return pointers to local vars if not needed) to reduce GC overhead.
Use golang.org/x/time/rate.Limiter or a Token Bucket implementation. Call Wait(ctx) before making a request.
Advanced: Architecture
Separates Domain Logic (core) from Infrastructure (DB, UI, API). Dependencies point inward. Adapters implement Port interfaces.
Handles AuthN/AuthZ, Rate Limiting, Routing, Protocol Translation (REST <-> gRPC). Keep logic minimal; don't put business logic in the gateway.
Manages distributed transactions. Choreography: Events trigger next step. Orchestration: Central coordinator tells services what to do. Use compensating transactions for rollback.
Advanced: Real-Time Systems
Prevents system overwhelm. mechanisms: Drop messages, Buffer (Queue), or Reject new work (Rate Limit). In Go: limit goroutines or use blocking channel sends.
Guaranteed only within a partition. Use the same Partition Key for related events (e.g., same UserID) to ensure sequential processing.
Advanced: Cloud & AWS
EC2: Persistent, control over OS, good for long-running, steady-state apps.
Lambda: Event-driven, ephemeral, scales to zero, good for bursty traffic or glue code.
Active-Active (complex data sync) or Active-Passive (easier). Use Global Load Balancer (Route53), Replicated DBs (DynamoDB Global Tables, Aurora Global), and stateless app tiers.
