Go (Golang) has become a primary language at a growing number of Indian product companies: Zerodha (almost exclusively Go), Razorpay (Go for payment-critical services), Flipkart, Swiggy, and several Indian fintech startups. If you are applying to these companies, knowing Go well is essential. This guide covers the Go concepts most commonly tested in Indian technical interviews, from beginner Go questions to advanced concurrency patterns.
Go fundamentals most tested in Indian interviews
Q: What are the main differences between Go and Java/Python? Go compiles to a single statically linked binary: no JVM, no interpreter. No exceptions (error handling via explicit return values). No class-based inheritance (interfaces + composition). Garbage collected but with low-latency GC. Goroutines (much lighter than OS threads: a Go programme can have millions). Built-in tooling: go fmt, go test, go vet, go mod.
Q: What is a goroutine and how does it differ from a thread? A goroutine is a lightweight execution unit managed by the Go runtime, not the OS. Initial stack size: 2KB (vs OS thread ~1–8MB). The Go scheduler multiplexes goroutines onto OS threads (M:N scheduling) with GOMAXPROCS threads (default: number of CPU cores). Starting a goroutine: `go functionName()`. Very cheap: launch hundreds of thousands concurrently.
Q: What is a channel in Go? A channel is a typed conduit for communication between goroutines. Channels are the idiomatic alternative to shared memory with locks. `ch := make(chan int)` (unbuffered: sender blocks until receiver is ready). `ch := make(chan int, 100)` (buffered: sender blocks only when buffer is full). Closing a channel: `close(ch)`: receiver gets zero value and ok=false after channel is drained.
Q: What is the select statement? Go's `select` blocks until one of multiple channel operations can proceed, then executes that case. If multiple cases are ready, one is chosen at random. `select { case v := <-ch1: ... case ch2 <- x: ... default: ... }`. The default case prevents blocking: runs if no case is immediately ready.
Go interfaces and composition
Q: How do Go interfaces work (implicit implementation)? In Go, a type implements an interface by implementing all its methods: no `implements` keyword. This is implicit satisfaction. Example: any type with a String() string method satisfies the fmt.Stringer interface. Enables duck typing: if a type has the right methods, it fits the interface.
Q: What is the empty interface and when do you use it? `interface{}` (or `any` since Go 1.18) accepts any type. Used when you truly don't know the type at compile time (JSON unmarshalling, fmt.Println). Avoid over-using it: it removes type safety and requires type assertions or type switches at runtime.
Q: What is a type assertion vs a type switch? Type assertion: `v, ok := i.(string)`: checks if interface value i holds a string. If ok is false, v is zero value (safe form). The unsafe form `v := i.(string)` panics if i is not a string. Type switch: `switch v := i.(type) { case string: ... case int: ... }`: checks multiple types cleanly.
Q: What is embedding in Go? Go uses composition over inheritance. You can embed a type inside a struct to 'inherit' its methods. `type AdminUser struct { User; adminLevel int }`: AdminUser has all User's methods promoted to it. Unlike Java inheritance, there is no polymorphism via embedding: only method promotion.
Go concurrency patterns and common pitfalls
Common concurrency patterns in Go interviews:
Worker pool: Fan out work from a channel to N goroutines. Common pattern for parallelising CPU-bound or I/O-bound work without uncontrolled goroutine growth.
Done channel / context cancellation: Signal goroutines to stop using a `done chan struct{}` or context.Context. Critical in production: goroutines that never stop are goroutine leaks.
Sync primitives: `sync.Mutex` for mutual exclusion over shared data. `sync.RWMutex` for read-heavy workloads (multiple concurrent readers, exclusive writers). `sync.WaitGroup` to wait for a group of goroutines to finish. `sync.Once` for one-time initialisation (singleton pattern in Go).
Common interview pitfalls:
- Race condition with a shared variable and goroutines: detect with `go test -race`. Fix with sync.Mutex or atomic operations.
- Goroutine leak: goroutine blocks on a channel that nobody writes to. Fix with context cancellation or buffered channels.
- Loop variable capture: `for i := range items { go func() { fmt.Println(i) }() }`: all goroutines may print the same value. Fix: pass i as an argument to the goroutine function.
- Forgetting to drain a channel before closing: `close(ch)` while a sender is still writing causes a panic.
Go interviews test concurrency knowledge that trips up candidates who know only Java or Python. Practise explaining goroutines, channels, and Go patterns with HireStepX's AI mock interviewer.
Practice freeGo Error Handling Patterns Interviewers Test
Go's explicit error handling is one of the most tested areas in Go interviews at Indian companies. The standard pattern of returning error as the last return value and checking it immediately is the foundation, but interviewers go deeper. Common follow-up questions include: how do you wrap errors to preserve context while adding information, what is the difference between fmt.Errorf with percent w versus percent v, and how do you use errors.Is and errors.As for type-checking wrapped errors. A common interview scenario is designing an error type hierarchy for a REST API where different error types need different HTTP status codes. Strong candidates define custom error types implementing the error interface rather than using fmt.Errorf strings, and use errors.As in the handler layer to unwrap to the specific type.
Go in Indian System Design Rounds
Go's characteristics make it particularly relevant in system design rounds at Indian companies that have adopted it. Interviewers at companies like Zerodha, Razorpay, and infrastructure teams at Flipkart may ask you to design systems and then probe Go-specific implementation decisions. Common Go system design questions include: how would you design a rate limiter using Go channels and goroutines, how do you handle graceful shutdown of an HTTP server in Go, and how would you design a worker pool for processing payment webhooks at high throughput. Understanding Go's net/http standard library, context propagation for request cancellation, and the implications of goroutine per request versus pooled goroutine models shows depth that separates candidates at senior engineer levels.
Frequently asked questions
Explore more