ExamAdda LogoExamAdda
PremiumDSA Animations
JAVASCRIPTMYSQLPYTHONINTERVIEWDBMSROADMAPSMACHINE LEARNING

JAVASCRIPT

  • JavaScript for Freshers
  • JavaScript for Intermediate
  • JavaScript Advanced
  • JavaScript Scenario Based Questions

Microservices

  • Microservices for Freshers
  • Microservices for Intermediate
  • Microservices Advanced

DBMS

  • DBMS for Freshers
  • DBMS for Intermediate
  • DBMS Advanced
  • DBMS Scenario-Based Questions

MongoDB

  • MongoDB for Freshers
  • MongoDB for Intermediate
  • MongoDB Advanced

TypeScript

  • TypeScript for Freshers
  • TypeScript for Intermediate
  • TypeScript Advanced
  • Frequently Asked Coding

ReactJs

  • ReactJs for Freshers
  • ReactJs for Intermediate
  • ReactJs Advanced

Python

  • Python for Freshers
  • Python for Intermediate
  • Python Advanced
  • Python Scenario-Based Questions

NODEJS

  • Nodejs for Freshers
  • NodeJS for Intermediate
  • Nodejs Advanced

DSA Interview

  • DSA for Freshers
  • DSA for Intermediate
  • DSA Advanced

Computer Network

  • Network for Freshers
  • Network for Intermediate
  • Network Advanced
  • Network Scenario Based Questions

Operating System

  • OS for Freshers
  • OS for Intermediate
  • OS Advanced

HTML

  • HTML for Freshers
  • HTML for Intermediate
  • HTML Advanced

CSS

  • CSS for Freshers
  • CSS for Intermediate
  • CSS Advanced

NEXTJS

  • NextJs for Freshers
  • NextJs for Intermediate
  • NextJs Advanced

C

  • C for Freshers
  • C for Intermediate
  • C Advanced

Golang

  • Golang for Freshers
  • Golang for Intermediate
  • Golang Advanced

Rust

  • Rust for Freshers
  • Rust for Intermediate
  • Rust Advanced
  • Rust Coding

HR

  • HR for Freshers
  • HR for Intermediate
  • HR Advanced

JAVA

  • Java for Freshers
  • Java for Intermediate
  • Java Advanced

Intermediate Golang Interview Questions and Answers (2026)

Last updated: May 10, 2026
Author :Jitendra KumarJitendra Kumar

*** 1. How Does the Go Scheduler Work?

In Go Programming Language, the scheduler manages the execution of goroutines efficiently over operating system threads.

Go uses the:

  • G-M-P model

Components of Scheduler

ComponentMeaning
GGoroutine
MOS Thread (Machine)
PProcessor/Logical Processor

How It Works

  • Goroutines (G) are assigned to processors (P)
  • Processors execute goroutines using OS threads (M)
  • Scheduler balances workloads automatically

Key Features

  • Lightweight concurrency
  • Fast context switching
  • Efficient CPU utilization

Interview Insight

Most interviewers expect:

  • Understanding of G-M-P model
  • Difference between goroutines and threads
  • Work-stealing scheduler concept

*** 2. Difference Between sync.Mutex and sync.RWMutex

Both are synchronization primitives used to protect shared resources.

Difference Table

Featuresync.Mutexsync.RWMutex
Access TypeOne reader/writerMultiple readers, one writer
Read PerformanceLowerBetter for read-heavy workloads
ComplexitySimpleSlightly complex

sync.Mutex Example

var mu sync.Mutex

mu.Lock()
// critical section
mu.Unlock()

sync.RWMutex Example

var mu sync.RWMutex

mu.RLock()
// read operation
mu.RUnlock()

mu.Lock()
// write operation
mu.Unlock()

Interview Insight

Use:

  • Mutex → balanced read/write workloads
  • RWMutex → read-heavy applications

*** 3. How Do You Prevent Deadlocks?

A deadlock occurs when goroutines wait indefinitely for resources.

Common Prevention Techniques

1. Always Unlock Mutexes

Use defer for safe unlocking.

mu.Lock()
defer mu.Unlock()

2. Avoid Circular Waiting

Do not create dependencies between goroutines.

3. Close Channels Properly

Improper channel handling can cause blocking.

4. Use Buffered Channels Carefully

Avoid full-buffer blocking situations.

5. Use Timeouts

Use select with time.After().

Example

select {

case msg := <-ch:
fmt.Println(msg)

case <-time.After(time.Second):
fmt.Println("Timeout")
}

Interview Insight

Deadlocks are common in:

  • Improper channel communication
  • Incorrect mutex usage

*** 4. How Do You Avoid Goroutine Leaks?

A goroutine leak happens when goroutines continue running unnecessarily and never terminate.

Prevention Techniques

1. Close Channels Properly

close(ch)

2. Use Context Cancellation

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

3. Avoid Infinite Blocking

Prevent goroutines from waiting forever.

4. Use WaitGroup

Ensure goroutines complete correctly.

Common Causes

  • Unclosed channels
  • Infinite loops
  • Blocked sends/receives

Interview Insight

Goroutine leaks can cause:

  • Memory issues
  • Resource exhaustion
  • Performance degradation

*** 5. Which Is Safer for Concurrent Access: Channels or Maps?

Channels are safer for concurrent communication because they are designed for synchronization.

Regular Go maps are not safe for concurrent writes.

Unsafe Map Example

m := make(map[string]int)

Concurrent writes can cause:

fatal error: concurrent map writes

Safer Alternatives

  • Channels
  • sync.Mutex
  • sync.Map

Interview Insight

Best answer:

“Channels are concurrency-safe for communication, while normal maps require synchronization.”


*** 6. What Are Race Conditions and How Do You Detect Them?

A race condition occurs when multiple goroutines access shared data simultaneously and at least one modifies it.

Example

count++

Concurrent updates may produce unpredictable results.

Detecting Race Conditions

Go provides the race detector.

Command

go run -race main.go

or

go test -race

Prevention Techniques

  • Mutex
  • Channels
  • Atomic operations

Interview Insight

Race detection is one of Go’s strongest debugging features.


*** 7. What Is a Worker Pool?

A worker pool is a concurrency pattern where multiple worker goroutines process tasks from a shared queue.

Benefits

  • Controlled concurrency
  • Better resource management
  • Improved scalability

Common Use Cases

  • API processing
  • Background jobs
  • Task queues

Worker Pool Structure

ComponentPurpose
Jobs ChannelReceives tasks
WorkersProcess tasks
Results ChannelReturns output

Interview Insight

Worker pools prevent excessive goroutine creation.


*** 8. How Do You Implement a Worker Pool?

A worker pool is implemented using:

  • Goroutines
  • Channels
  • WaitGroup

Example

package main

import (
"fmt"
"sync"
)

func worker(id int, jobs <-chan int, wg *sync.WaitGroup) {

defer wg.Done()

for job := range jobs {
fmt.Println("Worker", id, "processing", job)
}
}

func main() {

jobs := make(chan int, 5)

var wg sync.WaitGroup

for i := 1; i <= 3; i++ {
wg.Add(1)
go worker(i, jobs, &wg)
}

for j := 1; j <= 5; j++ {
jobs <- j
}

close(jobs)

wg.Wait()
}

Key Concepts

  • Job distribution
  • Concurrent processing
  • Synchronization

Interview Insight

Worker pools are frequently asked in backend and system-design interviews.


** 9. What Is a Pipeline in Go?

A pipeline is a sequence of stages connected using channels where output from one stage becomes input for the next stage.

Example Flow

Input -> Process -> Output

Features

  • Concurrent processing
  • Separation of concerns
  • Better scalability

Example

func square(in <-chan int, out chan<- int) {

for n := range in {
out <- n * n
}

close(out)
}

Interview Insight

Pipelines are heavily used in:

  • Data processing
  • Streaming systems
  • ETL workflows

** 10. What Is sync.Pool?

sync.Pool is used to temporarily store reusable objects to reduce memory allocations and improve performance.

Example

var pool = sync.Pool{
New: func() interface{} {
return "New Object"
},
}

Using Pool

obj := pool.Get()

pool.Put(obj)

Benefits

  • Reduced garbage collection pressure
  • Better performance
  • Object reuse

Common Use Cases

  • Buffers
  • Temporary objects
  • High-performance applications

Interview Insight

sync.Pool is mainly used in:

  • Performance-critical systems
  • High-throughput applications

** 11. What Is GOMAXPROCS?

In Go Programming Language, GOMAXPROCS controls the maximum number of CPU threads that can execute Go code simultaneously.

It determines how many OS threads can run goroutines in parallel.

Example

runtime.GOMAXPROCS(4)

Important Points

  • Default value = number of CPU cores
  • Controls parallelism, not concurrency
  • Managed by the Go scheduler

Package Required

import "runtime"

Interview Insight

Common interview question:

“Difference between concurrency and parallelism?”

  • Concurrency → multiple tasks managed together
  • Parallelism → tasks executed simultaneously

** 12. What Is runtime.Gosched()?

runtime.Gosched() voluntarily yields the processor, allowing other goroutines to run.

Example

runtime.Gosched()

Purpose

  • Improves goroutine scheduling
  • Prevents CPU monopolization
  • Helps cooperative multitasking

Example

package main

import (
"fmt"
"runtime"
)

func main() {

go func() {
fmt.Println("Goroutine")
}()

runtime.Gosched()

fmt.Println("Main")
}

Interview Insight

Gosched() pauses the current goroutine temporarily without blocking the thread.


** 13. What Is a Ticker in Go?

A ticker repeatedly sends values to a channel at fixed intervals.

It is provided by the time package.

Example

ticker := time.NewTicker(time.Second)

Receiving Tick Events

for t := range ticker.C {
fmt.Println(t)
}

Stopping Ticker

ticker.Stop()

Common Use Cases

  • Periodic tasks
  • Monitoring systems
  • Scheduled background jobs

Interview Insight

Difference:

  • Timer → executes once
  • Ticker → executes repeatedly

* 14. What Is a select Block Without a default Case?

A select block without a default case blocks until one channel operation becomes ready.

Example

select {

case msg := <-ch:
fmt.Println(msg)
}

Behavior

  • Waits indefinitely for channel activity
  • Synchronizes goroutines naturally

Important Point

If all channels are blocked:

  • select also blocks

Interview Insight

Adding a default case makes select non-blocking.


*** 15. How Does Garbage Collection Work in Go?

Go uses an automatic garbage collector (GC) to free unused memory.

The GC identifies objects that are no longer reachable and removes them.

Go GC Features

  • Automatic memory management
  • Concurrent garbage collection
  • Low pause times

GC Phases

PhasePurpose
MarkIdentify live objects
SweepRemove unused objects

Benefits

  • Prevents manual memory management
  • Reduces memory-related bugs
  • Improves developer productivity

Interview Insight

Go uses:

Concurrent Mark-and-Sweep Garbage Collection


*** 16. What Is a Memory Leak?

A memory leak occurs when memory is allocated but never released or reused properly.

In Go, leaks usually happen because objects remain referenced and cannot be garbage collected.

Common Causes

  • Goroutine leaks
  • Unclosed channels
  • Global references
  • Large unused slices

Example

var data [][]byte

If unused data remains referenced, memory usage grows continuously.

Interview Insight

Go has garbage collection, but memory leaks are still possible.


*** 17. How Do You Prevent Memory Leaks?

Common Prevention Techniques

1. Close Resources Properly

defer file.Close()

2. Avoid Goroutine Leaks

Use:

  • Context cancellation
  • Proper channel handling

3. Remove Unused References

Allow garbage collector to reclaim memory.

4. Limit Slice Retention

Avoid holding large underlying arrays unnecessarily.

5. Use Profiling Tools

Go provides:

pprof

Interview Insight

Most Go memory leaks are caused by:

  • Long-lived references
  • Stuck goroutines

*** 18. How Do You Optimize Go Code Performance?

Common Optimization Strategies

1. Reduce Memory Allocations

Reuse objects when possible.

2. Use Buffered Channels

Minimize blocking overhead.

3. Avoid Unnecessary Goroutines

Too many goroutines increase scheduling cost.

4. Use Efficient Data Structures

Choose proper:

  • Maps
  • Slices
  • Struct layouts

5. Benchmark Code

go test -bench=.

6. Profile Applications

Use:

pprof

7. Minimize Reflection

Reflection is slower than direct access.

Interview Insight

Performance optimization should always be:

  • Measured
  • Benchmarked
  • Profile-driven

*** 19. Strategies to Reduce GC Overhead

Effective Strategies

1. Reduce Object Allocations

Fewer allocations reduce GC workload.

2. Reuse Objects

Use:

sync.Pool

3. Avoid Temporary Objects

Minimize short-lived allocations.

4. Use Value Types Carefully

Large heap allocations increase GC pressure.

5. Preallocate Slices

make([]int, 0, 1000)

6. Reduce Pointer Usage

More pointers increase GC scanning work.

Interview Insight

GC performance becomes critical in:

  • High-throughput systems
  • Low-latency applications

*** 20. Performance Implications of Large Structs

Large structs can negatively impact performance because copying them requires more memory and CPU time.

Problems with Large Structs

  • Higher memory usage
  • Slower copying
  • Increased cache misses
  • More GC pressure

Example

type LargeStruct struct {
Data [10000]int
}

Passing this by value is expensive.

Better Approach

Use pointer receivers.

Example

func process(ls *LargeStruct) {
}

Optimization Tips

  • Use pointer receivers
  • Avoid unnecessary copies
  • Keep structs compact

Interview Insight

Struct field ordering can improve memory alignment and cache efficiency.

21. Difference Between Stack and Heap Allocation in Go

Stack Allocation

  • Memory is allocated inside the function call stack.
  • Allocation and deallocation are very fast.
  • Memory is automatically freed when the function returns.
  • Used for small, short-lived variables.

Example

func add() int {
x := 10
y := 20
return x + y
}

Here, x and y are usually stored on the stack.


Heap Allocation

  • Memory is allocated in the heap area.
  • Managed by Go Garbage Collector (GC).
  • Slightly slower because GC needs to track it.
  • Used when data must survive outside the function scope.

Example

func createUser() *User {
u := User{Name: "Go"}
return &u
}

u escapes the function, so it is allocated on the heap.


Key Differences

FeatureStackHeap
SpeedFasterSlower
Managed ByCompilerGarbage Collector
LifetimeFunction scopeUntil no references remain
Allocation CostCheapExpensive
GC ImpactNoYes

Interview Insight

Interviewers often ask:

  • “How does Go decide stack vs heap?”
  • “What causes heap allocation?”
  • “How does heap allocation affect performance?”

The answer is: Go uses escape analysis.


22. What is Escape Analysis?

Definition

Escape analysis is a compiler optimization technique used by Go to determine whether a variable should be allocated on the stack or heap.

If a variable “escapes” the function scope, Go allocates it on the heap.


Example

func test() *int {
x := 10
return &x
}

Here, x escapes because its address is returned.

So Go allocates x on the heap.


Non-Escaping Example

func test() int {
x := 10
return x
}

x does not escape, so it stays on the stack.


Check Escape Analysis

Use:

go build -gcflags="-m"

Example output:

moved to heap: x

Why It Matters

  • Heap allocations increase GC pressure.
  • More heap usage can reduce performance.
  • Reducing escaping variables improves efficiency.

Interview Tip

A common interview question:

“How can you reduce heap allocations in Go?”

Answer:

  • Avoid returning pointers unnecessarily.
  • Use value types when possible.
  • Minimize closures capturing variables.
  • Reuse objects using sync.Pool.

23. How Do You Optimize JSON Encoding/Decoding?

Common Optimization Techniques


1. Use Structs Instead of map[string]interface{}

Bad

var data map[string]interface{}
json.Unmarshal(b, &data)

Better

type User struct {
Name string `json:"name"`
Age int `json:"age"`
}

Structs are faster and type-safe.


2. Use jsoniter for High Performance

Standard library is good, but faster alternatives exist.

Example:

import jsoniter "github.com/json-iterator/go"

var json = jsoniter.ConfigCompatibleWithStandardLibrary

3. Reuse Buffers

var buf bytes.Buffer
json.NewEncoder(&buf).Encode(data)

Avoid repeated allocations.


4. Avoid Reflection Heavy Operations

Reflection is expensive.

Prefer:

  • concrete structs
  • typed fields
  • known schemas

5. Use Streaming for Large JSON

decoder := json.NewDecoder(file)

Avoid loading huge JSON into memory.


6. Use omitempty

Name string `json:"name,omitempty"`

Reduces payload size.


Interview Insight

Interviewers may ask:

  • Why is JSON slow?
  • Why is reflection expensive?
  • Difference between Marshal and Encoder?

Important point:
Go’s standard JSON package uses reflection internally.


24. What is the unsafe Package?

Definition

The unsafe package allows low-level memory manipulation in Go.

It bypasses Go’s type safety.


Common Uses

  • Pointer conversion
  • Memory optimization
  • Interacting with C libraries
  • High-performance systems programming

Example

package main

import (
"fmt"
"unsafe"
)

func main() {
x := 10
p := unsafe.Pointer(&x)

fmt.Println(*(*int)(p))
}

Important Components

FunctionPurpose
unsafe.PointerGeneric pointer type
unsafe.Sizeof()Size of variable
unsafe.Alignof()Memory alignment
unsafe.Offsetof()Field offset

Risks

  • Breaks type safety
  • Can cause memory corruption
  • May break across Go versions
  • Harder to maintain

Interview Insight

Important statement:

“Use unsafe only when absolutely necessary.”

Mostly used in:

  • runtime
  • serialization libraries
  • high-performance systems

25. Difference Between map and struct

Struct

  • Fixed fields
  • Compile-time type safety
  • Faster access
  • Better memory efficiency

Example

type User struct {
Name string
Age int
}

Map

  • Dynamic key-value storage
  • Flexible structure
  • Slower than struct
  • Uses hashing internally

Example

m := map[string]int{
"age": 25,
}

Key Differences

FeatureStructMap
SchemaFixedDynamic
PerformanceFasterSlower
Type SafetyStrongWeak
Memory UsageLowerHigher
Access MethodDirectHash lookup

When to Use

Use Struct When:

  • Schema is known
  • Performance matters
  • Strong typing needed

Use Map When:

  • Dynamic fields required
  • Unknown keys
  • Flexible JSON-like data

Interview Insight

Common question:

“Why are structs generally faster than maps?”

Answer:
Struct field access is direct memory access.
Map access requires hashing and bucket lookup.


26. What is a Nil Interface and Why is it Problematic?

Important Concept

An interface is nil only when:

  • type = nil
  • value = nil

Problem Example

type User struct{}

func main() {
var u *User = nil
var i interface{} = u

fmt.Println(i == nil)
}

Output:

false

Why?

Because interface internally stores:

(type, value)

In this case:

(*User, nil)

Type exists, so interface is not nil.


Internal Representation

interface = {
type
data
}

Both must be nil for interface to be nil.


Why It Causes Bugs

This commonly causes:

  • incorrect nil checks
  • panic situations
  • hidden runtime bugs

Proper Check

if i == nil {
// true only if both type and value nil
}

Or use reflection carefully when needed.


Interview Insight

This is one of the most commonly asked tricky Go interview questions.

Interviewers check whether candidates understand:

  • interface internals
  • runtime representation
  • typed nil behavior

27. Difference Between Value Receiver and Pointer Receiver

Value Receiver

Behavior

  • Receives a copy of the struct.
  • Original object is not modified.

Example

type User struct {
Name string
}

func (u User) change() {
u.Name = "Go"
}

Pointer Receiver

Behavior

  • Receives pointer to original struct.
  • Can modify original data.

Example

func (u *User) change() {
u.Name = "Go"
}

Key Differences

FeatureValue ReceiverPointer Receiver
Copies ObjectYesNo
Modify OriginalNoYes
Memory EfficientLessMore
Large Struct PerformanceWorseBetter

When to Use Pointer Receiver

Use pointer receiver when:

  • modifying struct
  • large struct
  • avoiding copies
  • consistency required

Interview Insight

A very common question:

“Can methods with pointer receivers satisfy interfaces?”

Yes.

But method sets matter.


Rule

  • Value can call both receiver types.
  • Pointer can call both receiver types.
  • Interface satisfaction depends on method set.

28. What is Deep Copy vs Shallow Copy in Go?

Shallow Copy

Definition

Copies only top-level structure.

Nested references still point to same memory.


Example

type User struct {
Scores []int
}

u1 := User{
Scores: []int{1,2,3},
}

u2 := u1
u2.Scores[0] = 100

Both objects change because slice references same array.


Deep Copy

Definition

Copies all nested data into new memory.

Objects become completely independent.


Example

u2 := User{
Scores: make([]int, len(u1.Scores)),
}

copy(u2.Scores, u1.Scores)

Now modifying u2 does not affect u1.


Key Differences

FeatureShallow CopyDeep Copy
Nested References SharedYesNo
Independent ObjectsNoYes
FasterYesNo
Memory UsageLowerHigher

Interview Insight

Go assignments are usually shallow copies.

Special care required for:

  • slices
  • maps
  • pointers
  • channels

29. Difference Between new and make

new

Purpose

Allocates memory and returns pointer.

Works with all types.

Example

p := new(int)

Equivalent:

var x int
p := &x

make

Purpose

Initializes built-in reference types.

Used only for:

  • slice
  • map
  • channel

Example

m := make(map[string]int)
s := make([]int, 5)
c := make(chan int)

Key Differences

Featurenewmake
ReturnsPointerInitialized object
InitializesNoYes
Used ForAny typeslice/map/channel

Important Interview Point

Wrong

m := new(map[string]int)

Map is still nil internally.

Correct

m := make(map[string]int)

Interview Insight

make is special because slices, maps, and channels require runtime initialization.


30. How Do Slices Internally Work?

Slice Structure

A slice internally contains:

pointer -> underlying array
length
capacity

Internal Representation

slice = {
ptr
len
cap
}

Example

s := []int{1,2,3}

Internally:

ptr -> array
len = 3
cap = 3

Append Behavior

Example

s := []int{1,2,3}
s = append(s, 4)

If capacity is full:

  1. New larger array allocated
  2. Old elements copied
  3. New element added

Important Concept

Slices are views over arrays.

Multiple slices can share same underlying array.


Example

a := []int{1,2,3,4}

b := a[:2]
c := a[:2]

b[0] = 100
fmt.Println(c[0])

Output:

100

Because both share same array.


Length vs Capacity

s := make([]int, 3, 5)
len = 3
cap = 5

Interview Insight

Very common questions:

  • How does append work internally?
  • When does reallocation happen?
  • Why do slices sometimes affect each other?
  • Difference between length and capacity?

31. How Are Maps Internally Implemented in Go?

Definition

Go maps are implemented as hash tables.

They provide:

  • fast lookup
  • insertion
  • deletion

Average complexity:

O(1)

Internal Structure

A Go map internally contains:

  • buckets
  • hash function
  • overflow buckets

How It Works

Step 1: Hashing

When you insert a key:

m["name"] = "Go"

Go:

  1. Computes hash of "name"
  2. Finds bucket using hash
  3. Stores key-value pair inside bucket

Buckets

Each bucket stores:

  • multiple key-value pairs
  • usually up to 8 entries

If bucket becomes full:

  • overflow bucket is created

Internal Representation

map
├── bucket array
│ ├── bucket 1
│ ├── bucket 2
│ └── ...

Collision Handling

Two keys may generate same bucket.

This is called:

hash collision

Go handles collisions using:

  • overflow buckets

Map Growth

When map becomes large:

  • Go allocates new buckets
  • entries are gradually moved

This is called:

incremental resizing

Important Properties

FeatureDetails
Ordered?No
Thread Safe?No
Lookup SpeedAverage O(1)
Uses HashingYes

Why Maps Are Not Thread-Safe

Concurrent writes can corrupt internal buckets.

Example:

fatal error: concurrent map writes

Use:

  • mutex
  • sync.Map

for concurrent access.


Interview Insight

Very common interview questions:

  • Why are maps fast?
  • How are collisions handled?
  • Why are maps not thread-safe?
  • What happens during resizing?

32. What is Shadowing in Go?

Definition

Shadowing happens when a variable declared in an inner scope has the same name as a variable in an outer scope.

The inner variable hides the outer variable.


Example

x := 10

if true {
x := 20
fmt.Println(x)
}

fmt.Println(x)

Output:

20
10

Inside block:

  • new x is created
  • outer x becomes hidden

Common Real-World Bug

file, err := os.Open("a.txt")

if err != nil {
return err
}

if data, err := io.ReadAll(file); err != nil {
return err
}

Inner err shadows outer err.

This can create debugging confusion.


Why It Is Dangerous

Shadowing may cause:

  • hidden bugs
  • unexpected values
  • logic errors
  • difficult debugging

Best Practices

Avoid Reusing Variable Names

Prefer:

data, readErr := io.ReadAll(file)

instead of:

data, err := io.ReadAll(file)

Interview Insight

Interviewers often ask:

“Why is := sometimes dangerous?”

Because it may accidentally create a new variable instead of updating existing one.


33. Best Practices for Error Handling in Go

1. Handle Errors Explicitly

Go prefers explicit error handling.

Example

data, err := readFile()

if err != nil {
return err
}

2. Add Context to Errors

Bad:

return err

Better:

return fmt.Errorf("failed to read file: %w", err)

Adds debugging information.


3. Avoid Ignoring Errors

Bad:

data, _ := readFile()

Ignored errors can cause production failures.


4. Use Sentinel Errors Carefully

Prefer:

  • wrapped errors
  • custom errors

instead of many global variables.


5. Keep Errors Simple

Good error messages:

failed to connect database
invalid user id

Avoid:

Error occurred!!!

6. Don’t Use panic for Normal Errors

Use panic only for:

  • unrecoverable situations
  • programmer mistakes

7. Use errors.Is and errors.As

Modern Go error handling:

if errors.Is(err, os.ErrNotExist) {
}

8. Return Early

Prefer:

if err != nil {
return err
}

instead of nested logic.


Interview Insight

Go interviewers strongly evaluate:

  • clean error handling
  • readable code
  • proper wrapping
  • debugging clarity

34. How Do You Design Custom Error Types?

Why Custom Errors?

Custom errors allow:

  • additional context
  • structured error handling
  • type checking

Basic Custom Error

Example

type ValidationError struct {
Field string
}

func (e ValidationError) Error() string {
return "invalid field: " + e.Field
}

Usage

func validate(age int) error {
if age < 18 {
return ValidationError{
Field: "age",
}
}

return nil
}

Type Assertion

err := validate(10)

if v, ok := err.(ValidationError); ok {
fmt.Println(v.Field)
}

Modern Approach Using errors.As

var v ValidationError

if errors.As(err, &v) {
fmt.Println(v.Field)
}

Best Practices

Include Useful Context

Good:

type APIError struct {
StatusCode int
Message string
}

Keep Error Messages Human Readable

Example:

user not found
payment failed

Support Wrapping

func (e APIError) Error() string {
return e.Message
}

Interview Insight

Interviewers often ask:

  • Why use custom errors?
  • Difference between sentinel and custom errors?
  • Why use errors.As?

35. What is Deferred Execution?

Definition

defer delays execution of a function until the surrounding function returns.


Example

func main() {
defer fmt.Println("world")

fmt.Println("hello")
}

Output:

hello
world

Common Uses

1. Closing Files

file, _ := os.Open("a.txt")
defer file.Close()

2. Unlocking Mutexes

mu.Lock()
defer mu.Unlock()

3. Cleanup Operations

defer cleanup()

Important Property

Deferred calls execute in:

LIFO order

(last in, first out)


Example

defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)

Output:

3
2
1

Interview Insight

Very common interview questions:

  • When does defer execute?
  • In what order do deferred calls run?
  • Does defer affect performance?

36. How Does defer Work Internally?

Internal Mechanism

When Go sees:

defer f()

It:

  1. Stores deferred call in stack-like structure
  2. Executes deferred calls before function exits

Important Detail

Arguments are evaluated immediately.


Example

x := 10

defer fmt.Println(x)

x = 20

Output:

10

Because argument captured at defer time.


LIFO Execution

Deferred functions run in reverse order.


Named Return Value Example

func test() (x int) {
defer func() {
x++
}()

return 5
}

Output:

6

Deferred function can modify named return values.


Performance Consideration

Older Go versions:

  • defer was expensive

Modern Go:

  • optimized significantly

Still avoid defer inside extremely hot loops when performance critical.


Interview Insight

Interviewers frequently ask:

  • Are defer arguments evaluated immediately?
  • Can defer modify return values?
  • Why is defer useful?

37. When Should You Use panic?

Definition

panic stops normal execution of the current goroutine.

Used for:

  • unrecoverable situations
  • programmer errors

Example

panic("something went wrong")

Appropriate Use Cases

1. Impossible States

default:
panic("unexpected state")

2. Initialization Failures

if db == nil {
panic("database init failed")
}

3. Programmer Mistakes

Example:

  • invalid assumptions
  • corrupt internal state

When NOT to Use panic

Do NOT use panic for:

  • normal business errors
  • validation failures
  • user input errors

Instead:

return error

panic vs error

Featurepanicerror
RecoverableUsually NoYes
UsageCritical failuresNormal failures
Stops FlowYesNo

Interview Insight

Important statement:

“panic is exceptional, not normal control flow.”


38. How Do You Recover from panic in Goroutines?

Important Rule

recover() only works inside a deferred function.


Example

func worker() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered:", r)
}
}()

panic("boom")
}

Why Goroutines Matter

A panic inside goroutine can crash the entire program if not recovered.


Safe Goroutine Pattern

go func() {
defer func() {
if r := recover(); r != nil {
log.Println("panic recovered:", r)
}
}()

process()
}()

Important Interview Point

Recovery only works in:

  • same goroutine

You cannot recover panic from another goroutine.


Common Production Use Cases

  • worker pools
  • HTTP servers
  • background jobs

Interview Insight

Frequently asked:

“Can main goroutine recover panic from child goroutine?”

Answer:

No

Each goroutine needs its own recovery mechanism.


39. What is Sentinel Error in Go?

Definition

A sentinel error is a predefined reusable error value.

Usually declared as global variable.


Example

var ErrNotFound = errors.New("not found")

Usage

if err == ErrNotFound {
}

Modern Preferred Approach

Use:

errors.Is(err, ErrNotFound)

instead of direct comparison.


Standard Library Examples

io.EOF
os.ErrNotExist
context.Canceled

Advantages

  • reusable
  • easy comparisons
  • standardized errors

Disadvantages

  • tight coupling
  • global dependency
  • less flexible

Best Practice

Use sentinel errors only when:

  • callers must identify specific error

Interview Insight

Common interview question:

“Why is errors.Is preferred over == ?”

Because wrapped errors may not match direct equality.


40. What is Error Wrapping?

Definition

Error wrapping means adding extra context while preserving the original error.

Introduced officially in:

Go 1.13

Example

if err != nil {
return fmt.Errorf("failed to read config: %w", err)
}

%w wraps original error.


Benefits

  • preserves original error
  • adds debugging context
  • supports error chains

Checking Wrapped Errors

errors.Is

if errors.Is(err, os.ErrNotExist) {
}

Extracting Error Types

errors.As

var pathErr *os.PathError

if errors.As(err, &pathErr) {
}

Error Chain Example

API Error
└── DB Error
└── Network Error

Why Wrapping Is Important

Without wrapping:

  • original cause gets lost

With wrapping:

  • debugging becomes easier

Interview Insight

Most commonly asked points:

  • Difference between %v and %w
  • Why use errors.Is?
  • What is error chain?
  • How does errors.As work?









Premium Content

Sign in to check if you have access to this premium tutorial, or upgrade to premium.

Sign in to Unlock
Previous Tutorial
Golang for Freshers
Next Tutorial
Golang Advanced
ExamAdda LogoExamAdda Tech

Your comprehensive destination for learning programming, web development, data science, and modern technologies. Master coding with our in-depth tutorials and practical examples.

Support

  • About Us
  • Contact Us
  • Privacy Policy
  • Terms of Service

Connect With Us

Follow us on social media for the latest tutorials, tips, and programming updates.

© 2026 ExamAdda Tech. All rights reserved.

Privacy PolicyTerms of ServiceCookie Policy