Go (Golang) is the fastest-growing backend language at Indian product companies, favoured for its simplicity, performance, and concurrency model. Razorpay, Zerodha, PhonePe, and Swiggy are among the companies using Go for their most performance-critical services. This guide covers Go interview questions for Indian companies in 2026.
Go fundamentals: types, functions, and packages
Go language fundamentals:
1. Go's key design philosophy: Go is designed for simplicity, readability, and fast compilation. Key features: static typing, garbage collection, built-in concurrency (goroutines and channels), fast compilation (compiles to a single binary), and a strict, opinionated standard library. No classes, no inheritance, no generics in early versions (generics were added in Go 1.18).
2. Go types: - Basic types: int, int64, float64, string, bool, byte (alias for uint8), rune (alias for int32, represents a Unicode code point) - Composite types: array (fixed-size), slice (dynamic, most commonly used), map (key-value), struct (custom composite types) - Pointers: Go has pointers but no pointer arithmetic. & takes the address of a variable; * dereferences a pointer - Zero values: every type has a zero value (0 for numbers, "" for strings, nil for pointers/slices/maps/channels/functions)
3. Functions: Go functions can return multiple values (this is how error handling works). Named return values allow early return with just return (defer populates them). Variadic functions accept a variable number of arguments (...T).
4. Packages and modules: Every Go file belongs to a package. The main package is the entrypoint. Package names are lowercase, single words. Go modules (introduced in Go 1.11): a go.mod file defines the module path and dependencies. go get adds dependencies; go mod tidy removes unused ones.
5. Methods and receivers: Go has no classes but types can have methods. A method is a function with a receiver: func (u *User) FullName() string { return u.FirstName + ' ' + u.LastName }. Pointer receiver (most common): can modify the receiver; value receiver: gets a copy. Use pointer receivers consistently for a type (for both methods that modify and methods that don't).
Goroutines, channels, and the concurrency model
Go concurrency interview questions:
1. Goroutines: A goroutine is a lightweight concurrent function. go func(): starts the function as a goroutine. Goroutines are managed by the Go runtime, not the OS. Go can run hundreds of thousands of goroutines concurrently (the runtime multiplexes them onto OS threads using M:N scheduling). The Go runtime includes a work-stealing scheduler that distributes goroutines efficiently across available CPU cores.
2. Channels: Channels are typed pipes for communication between goroutines. The Go motto: 'Do not communicate by sharing memory; share memory by communicating.' ch := make(chan int): creates an unbuffered channel. Send: ch <- 42. Receive: v := <-ch. Unbuffered channel: send blocks until a receiver is ready (synchronous hand-off). Buffered channel: make(chan int, 10): sends do not block until the buffer is full.
3. Select statement: Selects on multiple channel operations; runs whichever case is ready first: ```go select { case msg := <-ch1: fmt.Println('received from ch1:', msg) case msg := <-ch2: fmt.Println('received from ch2:', msg) case <-time.After(5 * time.Second): fmt.Println('timeout') } ``` If multiple cases are ready, one is chosen at random. Used for: timeouts, fan-in (merging multiple channels), and checking if a channel is ready without blocking.
4. sync package: sync.Mutex: mutual exclusion lock; use when goroutines must share a data structure (counter, cache). Lock() / Unlock() to protect critical sections; defer mu.Unlock() to ensure release even on panic. sync.WaitGroup: wait for a collection of goroutines to finish. Add(n) before starting goroutines; each goroutine calls Done() when finished; Wait() blocks until Done() has been called n times. sync.Once: execute a function exactly once (initialise a singleton safely). sync.RWMutex: allows multiple concurrent readers but only one writer.
Go interfaces, error handling, and stdlib
Go advanced concepts:
1. Interfaces in Go: Go interfaces are satisfied implicitly (duck typing): a type implements an interface just by having the right methods, without explicitly declaring it. No 'implements' keyword. This is Go's primary mechanism for polymorphism and testability: ```go type Writer interface { Write([]byte) (int, error) }
type FileWriter struct { file *os.File } func (f FileWriter) Write(data []byte) (int, error) { return f.file.Write(data) }
// FileWriter automatically implements Writer because it has the Write method ```
The empty interface interface{} (or any in Go 1.18+) accepts any value. Use it only when truly necessary; prefer typed interfaces.
2. Error handling: Go does not have exceptions. Functions signal errors by returning an error as the last return value: ```go func readFile(path string) ([]byte, error) { data, err := os.ReadFile(path) if err != nil { return nil, fmt.Errorf('readFile: %w', err) } return data, nil } ``` - %w in fmt.Errorf wraps the error (preserves the original error for errors.Is and errors.As) - errors.Is(err, target): checks if err is or wraps the target error - errors.As(err, &target): extracts the first error in the chain that can be assigned to the target type - Custom error types: implement the error interface (Error() string method) for structured errors with fields
3. Important standard library packages: - net/http: HTTP server and client (the standard web server in Go is simple and built-in) - encoding/json: JSON marshaling/unmarshaling (json.Marshal, json.Unmarshal, struct field tags: json:"field_name") - context: cancellation and deadlines; always pass ctx as the first argument to functions that do I/O - sync: concurrency primitives (Mutex, WaitGroup, Once) - testing: unit test framework (TestXxx functions, t.Error, t.Fatal, subtests with t.Run)
Practise Go/Golang interview questions with HireStepX's AI voice interviewer. Get scored feedback on your explanations of goroutines, channels, and Go's concurrency model. First 2 sessions free.
Practice freeGo web services and microservices patterns
Go for web services and microservices:
1. HTTP server in Go: The net/http package includes a production-ready HTTP server: ```go func helloHandler(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(map[string]string{"message": "hello"}) }
func main() { mux := http.NewServeMux() mux.HandleFunc('/hello', helloHandler) http.ListenAndServe(':8080', mux) } ```
Popular Go web frameworks (optional, not required for simple services): Gin (most popular: adds routing parameters, middleware, validation), Chi (idiomatic, lightweight), Echo, Fiber. When to use a framework: when you need advanced routing (path parameters, groups, middleware composition) that the standard library does not provide cleanly.
2. Context for cancellation: The context.Context type carries deadlines, cancellation signals, and request-scoped values. Always pass ctx as the first parameter to functions that do I/O. http.Request already has a context (r.Context()); use it for all downstream calls. context.WithTimeout: create a context that automatically cancels after a duration: ```go ctx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() resp, err := client.Do(req.WithContext(ctx)) ```
3. gRPC in Go: gRPC (Protocol Buffers over HTTP/2) is widely used for inter-service communication in Go microservices (especially at Razorpay, Swiggy, and cloud-native companies). Define the service in a .proto file; the protoc compiler generates Go client and server code; implement the server interface. gRPC advantages over REST: binary protocol (smaller payload), strongly typed (protobuf schema = contract), bidirectional streaming, and built-in load balancing.
4. Dependency injection in Go: Go applications typically use constructor functions (not magic injection frameworks) to wire dependencies. Google's Wire tool generates dependency injection boilerplate from provider functions. For simple services, manual wiring (in main.go) is usually cleaner than a DI framework.
Frequently asked questions
Explore more