Go Lang Interview Questions and Answers 2026

1. What is Go and why is it popular?

Go is an open-source programming language developed by Google. It is designed for simplicity, concurrency, fast compilation, and scalability.

Key advantages:

  • Simple syntax
  • Fast execution
  • Built-in concurrency (goroutines)
  • Garbage collection
  • Strong standard library
  • Great for microservices and cloud systems

2. What are goroutines?

Goroutines are lightweight threads managed by the Go runtime.

Example:

go myFunction()
Features:
  • Very low memory usage
  • Faster than OS threads
  • Used for concurrent programming

3. What is a channel in Go?

Channels are used for communication between goroutines.

Example:

ch := make(chan int)

go func() {
    ch <- 10
}()

value := <-ch
fmt.Println(value)
Benefits:
  • Safe communication
  • Synchronization between goroutines
  • Avoids shared memory issues

4. Difference between buffered and unbuffered channels?

Unbuffered Channel

  • Sender waits until receiver receives data.
ch := make(chan int)

// Create an unbuffered channel of ints

ch := make(chan int)   // capacity = 0  → every send blocks until a receive

go func() {

ch <- 42           // blocks here until the main goroutine receives

}()

v := <-ch              // unblocks the sender, value is now 42

fmt.Println(v)         // Output: 42

Unbuffered (make(chan T))
Capacity 0
Send (ch <- v) Blocks until some goroutine receives
Receive (<-ch) Blocks until some goroutine sends
Typical uses Hand‑off / rendezvous, strict sequencing
Buffered Channel
  • Sender can send until buffer is full.
ch := make(chan int, 3)

ch <- 1                  // does not block yet

ch <- 2

ch <- 3                  // still fine: buffer now full

// ch <- 4 would block because the buffer is full

fmt.Println(<-ch)        // prints 1, frees one slot

ch <- 4                  // now this send succeeds immediately

Key points

Buffered (make(chan T, n))
Capacity n > 0
Send (ch <- v) Blocks only when buffer is full
Receive (<-ch) Blocks only when buffer is empty
Typical uses Smooth out bursts, worker pools, rate limiting

 

Feature Unbuffered Channel Buffered Channel
Blocking behavior Sender blocks until receiver receives Sender only blocks when buffer is full
Synchronization Provides direct handoff Acts like a queue
Capacity make(chan T) make(chan T, N) (N > 0)
Common use case Safe communication & coordination Asynchronous buffering, pipelines

5. What is the difference between concurrency and parallelism?

Concurrency

Handling multiple tasks at the same time.

Parallelism

Executing multiple tasks simultaneously using multiple CPUs.

Go supports both using goroutines.


6. What is GOMAXPROCS?

GOMAXPROCS sets the maximum number of OS threads executing Go code simultaneously.

Example:

runtime.GOMAXPROCS(4)

7. What are pointers in Go?

Pointers store memory addresses.

Example:

x := 10
p := &x

fmt.Println(*p)
Notes:
  • Go supports pointers
  • No pointer arithmetic

8. What is the difference between new() and make()?

new()

Allocates memory and returns pointer.

p := new(int)
make()

Initializes slices, maps, and channels.

m := make(map[string]int)

9. What are slices in Go?

Slices are dynamic views over arrays.

Example:

nums := []int{1,2,3}
Features:
  • Dynamic size
  • Backed by arrays
  • Contains length and capacity

10. Difference between array and slice?

Array Slice
Fixed size Dynamic size
Value type Reference-like
Size part of type Flexible

11. What is the difference between len and cap?

len

Current number of elements.

  • The number of elements currently stored in the slice.
  • It’s the size of the slice you can directly access.
  • Cannot be negative, always ≤ capacity.

cap

Maximum capacity before reallocation.

  • The total number of elements the slice can hold before needing to allocate more memory.
  • It’s the maximum size the slice can grow to without reallocating.
  • Length → how many elements are actually in the slice.
  • Capacity → how many elements it can hold before reallocating.

Example:

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

fmt.Println(len(s)) // 3
fmt.Println(cap(s)) // 5

12. What are interfaces in Go?

Interfaces define behavior.

Example:

type Animal interface {
    Speak()
}
Important:
  • Implicit implementation
  • No implements keyword

13. What is an empty interface?

interface{}
It can hold values of any type.

Equivalent to:

any

14. What is type assertion?

Used to extract concrete value from interface.

Example:

var i interface{} = "hello"
s := i.(string)
Safe assertion:
s, ok := i.(string)

15. What is a struct?

Structs group related data fields.

Example:

type User struct {
    Name string
    Age  int
}

16. Does Go support inheritance?

Go does not support classical inheritance.

Instead, it uses:

  • Composition
  • Embedding

Example:

type Engine struct {}

type Car struct {
    Engine
}

17. What is embedding in Go?

Embedding allows one struct to include another struct directly.

It promotes composition over inheritance.


18. What is defer?

defer delays execution until surrounding function returns.

Example:

defer fmt.Println("done")
Common uses:
  • Closing files
  • Unlocking mutexes
  • Cleanup tasks

19. What is panic and recover?

panic

Stops normal execution.

panic("error")
recover

Catches panic inside deferred functions.

defer func() {
    recover()
}()

20. What is garbage collection in Go?

Go automatically frees unused memory using garbage collection.

Benefits:

  • Reduces memory leaks
  • Easier memory management

21. What is a mutex?

Mutex prevents race conditions.

Example:

var mu sync.Mutex

mu.Lock()
counter++
mu.Unlock()

22. What is a race condition?

When multiple goroutines access shared data simultaneously causing unexpected behavior.

Go provides race detector:

go run -race main.go

23. What is context package used for?

The context package is used for:

  • Cancellation
  • Timeouts
  • Passing request-scoped values

Example:

ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()

24. What is select statement?

In Golang, select is a control statement used to wait on multiple channel operations at the same time.
It’s like a switch statement, but instead of matching values, it waits until one of the channel operations can proceed.

Key Points

  • select works only with channels.
  • It picks one case at random if multiple cases are ready.
  • Useful for concurrency, timeouts, and non-blocking channel reads/writes.
  • It also supports a default case for non-blocking behavior.

Basic Syntax

select {

case msg1 := <-ch1:

fmt.Println(“Received from ch1:”, msg1)

case msg2 := <-ch2:

fmt.Println(“Received from ch2:”, msg2)

case ch3 <- “data”:

fmt.Println(“Sent to ch3”)

default:

fmt.Println(“No channel operation ready”)

}

When to Use select

  • Waiting for messages from multiple channels.
  • Implementing timeouts.
  • Writing non-blocking channel operations.
  • Coordinating goroutines.

select works with multiple channels.

Example:

select {
case msg := <-ch1:
    fmt.Println(msg)
case <-time.After(time.Second):
    fmt.Println("timeout")
}

25. What are packages in Go?

Packages organize reusable code.

Every Go file starts with:

package main

26. Difference between process and thread?

Process Thread
Independent execution unit Lightweight execution path
More memory Less memory
Slower context switch Faster context switch

Goroutines are lighter than threads.


27. What are maps in Go?

Maps store key-value pairs.

Example:

m := map[string]int{
    "a": 1,
}
Check existence:
v, ok := m["a"]

28. Can Go functions return multiple values?

Yes.

Example:

func divide(a, b int) (int, error)

29. What are variadic functions? & how to return multiple variable in variadic function in Golang

Functions accepting variable arguments.

Example:

func sum(nums ...int)

In Go you can freely mix variadic parameters ( …T ) with multiple return values.
Just remember:

  1. Only one parameter—the last one—may be variadic.
  2. Return values are listed in parentheses, and you can optionally give them names.
  3. Callers receive the results as separate variables (not a struct or slice).

// SumAndAvg returns both the sum and the average of any number of ints.

func SumAndAvg(nums …int) (sum int, avg float64) {

for _, n := range nums {

sum += n

}

if len(nums) > 0 {

avg = float64(sum) / float64(len(nums))

}

return // named returns → `sum`, `avg` are returned implicitly

}

func main() {

s, a := SumAndAvg(3, 5, 7, 9)

fmt.Println(“sum:”, s, “avg:”, a) // sum: 24 avg: 6

}

Tips & Gotchas

Topic Note
Named vs unnamed returns Named results let you return without arguments; unnamed require return v1, v2.
Zero arguments A variadic call with no arguments passes an empty slice (len(nums)==0). Handle it if needed.
Forwarding Inside another variadic function, forward like OtherFunc(vals…) — the trailing … is required.
Performance Variadic parameters are allocated as a slice; if you call in hot loops with only a few items, consider explicit slice arguments instead.

30. What is dependency management in Go?

Go uses modules.

Initialize:

go mod init app
Install package:
go get package-name

Advanced Golang Interview Questions

31. Explain scheduler in Go.

Go scheduler manages goroutines using:

  • G → Goroutine
  • M → OS Thread
  • P → Processor

Known as GMP model.


32. What is channel deadlock?

Occurs when goroutines wait forever.

Example:

ch := make(chan int)
ch <- 1 // deadlock

33. What is sync.WaitGroup?

Waits for goroutines to finish.

Example:

var wg sync.WaitGroup

wg.Add(1)

go func() {
    defer wg.Done()
}()

wg.Wait()

34. What are worker pools in Go?

Pattern for limiting concurrent goroutines using channels and workers.

Common in:

  • APIs
  • Job processing
  • Background tasks

35. What is the difference between nil slice and empty slice?

Nil slice

var s []int

Empty slice

s := []int{}

Both have length 0, but nil slice equals nil.


36. What are common Go design principles?

  • Simplicity
  • Composition over inheritance
  • Explicit error handling
  • Concurrency-first design

37. what is diff bet timer and ticker in Golang

In Golang, **time.Timer** and **time.Ticker** are both types provided by the time package, but they serve different purposes:

timer := time.NewTimer(5 * time.Second)

<-timer.C

fmt.Println(“Timer fired after 5 seconds”)

  • Fires only once after 5 seconds.
  • Useful for delays, timeouts, etc.

🔁 Resetting:

You can reset a timer with .Reset() to reuse it.

Ticker

Used to repeatedly fire events at regular intervals.

📦 Example:

go

CopyEdit

ticker := time.NewTicker(2 * time.Second)

defer ticker.Stop()

for t := range ticker.C {

fmt.Println(“Tick at”, t)

}

  • Fires every 2 seconds continuously.
  • Useful for polling, periodic tasks, etc.
  • Summary of Differences
Feature time.Timer time.Ticker
Fires how often Once after duration Repeatedly at fixed intervals
Channel <-timer.C <-ticker.C
Use case Timeouts, delays Periodic jobs, polling
Stop method timer.Stop() ticker.Stop()

38.why use underscore in Golang

In Go, the underscore (_) is called the blank identifier, and it is used as a “write-only” variable. You can assign a value to it, but you cannot read from it.

When a function returns multiple values and you only care about some of them:

value, _ := someFunction()

Example:

count, _ := fmt.Println(“Hello”)

Here, fmt.Println returns (int, error) — if you don’t care about the error, use _.

If you’re iterating and don’t need the index or value:

for _, val := range []string{“a”, “b”, “c”} {

fmt.Println(val)

}

🔒 Why is this useful?

Go is strict — it does not allow unused variables or imports, even temporarily.

Summary Table

Use Case Example
Ignore extra return values _, err := someFunc()
Import for side effects import _ “github.com/lib/pq”
Ignore loop index/value for _, v := range items
Interface compliance check var _ MyInterface = (*MyType)(nil)
Avoid unused variable error _ = someFunc()

 

39.How to define map in Golang

In Go, a map is a built-in data type used to store key-value pairs, similar to dictionaries in Python or objects in JavaScript.

var m map[keyType]valueType

m := make(map[string]int)  // map of string keys to int values

Example:

package main

import “fmt”

func main() {

ages := make(map[string]int)

ages[“Alice”] = 30

ages[“Bob”] = 25

fmt.Println(ages)          // map[Alice:30 Bob:25]

fmt.Println(ages[“Bob”])   // 25

}

Operation Syntax / Example
Declare var m map[string]int
Initialize m := make(map[string]int)
Add value m[“key”] = value
Access value m[“key”]
Check existence val, ok := m[“key”]
Delete key delete(m, “key”)
Loop for k, v := range m { … }

40.How to identify which type of value saving in interface in Golang ex int string

Type Assertion

var i interface{} = “hello”

str, ok := i.(string)

if ok {

fmt.Println(“i is a string:”, str)

} else {

fmt.Println(“i is not a string”)

}

  • You can also try to assert other types: i.(int), i.(float64), etc.
  • The ok idiom prevents a panic if the assertion fails.
Method Use Case Example
Type assertion To extract known type v, ok := i.(string)
Type switch To handle multiple types cleanly switch v := i.(type) {}
reflect.TypeOf() For logging / generic inspection reflect.TypeOf(i)

41.what is difference define variable and initialization in Golang

This means telling the compiler that a variable exists, along with its type — but not giving it a value yet.

✅ 2. Variable Initialization

This means giving the variable a starting value

42.what is design pattern in Golang

In Golang, a design pattern is a reusable solution to a common software problem or scenario. These patterns are not specific to Go—they come from general software engineering—but they can be implemented in Go idiomatically.

In Golang, a design pattern is a reusable solution to a common software problem or scenario. These patterns are not specific to Go—they come from general software engineering—but they can be implemented in Go idiomatically.

  • Structured ways to solve recurring problems in software design
  • Promote code reusability, maintainability, and clarity
  • Common across languages, but Go has its own minimalistic and idiomatic style
  • Categories of Design Patterns
Category Purpose Common Patterns
Creational Deal with object creation Singleton, Factory, Builder, Prototype
Structural Deal with composition of objects Adapter, Decorator, Facade, Proxy
Behavioral Deal with communication between objects Strategy, Observer, Command, State
Concurrency (Go-specific) Handle concurrent behavior Worker Pool, Pipeline, Fan-In/Fan-Out

 

  1. Singleton Pattern

Ensures a class has only one instance and provides a global point of access.

package singleton

import “sync”

var once sync.Once

var instance *Database

type Database struct {

// config fields

}

func GetInstance() *Database {

once.Do(func() {

instance = &Database{}

})

return instance

}

  1. Factory Pattern

Used to create objects without specifying the exact type.

type Shape interface {

Draw()

}

 

type Circle struct{}

func (c Circle)

Draw()

{

fmt.Println(“Circle”)

}

func ShapeFactory(t string) Shape {

switch t {

case “circle”:

return Circle{}

}

return nil

}

  1. Strategy Pattern

Allows switching between algorithms at runtime.

go

CopyEdit

type PaymentStrategy interface {

Pay(amount float64)

}

type CreditCard struct{}

func (cc CreditCard) Pay(amount float64) {

fmt.Println(“Paid with credit card:”, amount)

}

type PayPal struct{}

func (pp PayPal) Pay(amount float64) {

fmt.Println(“Paid with PayPal:”, amount)

}

func ProcessPayment(strategy PaymentStrategy, amount float64) {

strategy.Pay(amount)

}

  1. Worker Pool (Concurrency Pattern – Go idiomatic)

func worker(id int, jobs <-chan int, results chan<- int) {

for j := range jobs {

fmt.Printf(“worker %d processing job %d\n”, id, j)

results <- j * 2

}

}

🧠 Why Use Design Patterns in Go?

  • Go encourages simplicity and composition over inheritance
  • Many classic OOP patterns (like inheritance-based ones) are adapted differently in Go
  • Channels, interfaces, and goroutines provide Go-specific design capabilities

🎯 When Should You Use Patterns?

  • When solving a problem that occurs repeatedly
  • When you want to structure your code for clarity and reusability
  • When building systems that need scalability, flexibility, and testability

43.How to consider all factors to design new project in Golang like memory management db etc.

2  High‑Level Architecture

  1. Service style
    • Monolith, modular monolith, or microservices
    • Consider Hexagonal / Clean Architecture for clearer boundaries.
  2. Interface contracts
    • gRPC for low‑latency internal calls, REST/JSON for public APIs.
    • Add OpenAPI or protobuf specs at day 0.
  3. Concurrency model
    • Goroutine per request, worker pools, or event loop?
    • Use context.Context everywhere for cancellation & deadlines.
  4. Data storage decision matrix
Need DB choice
Strict ACID, complex joins Postgres/MySQL
Horizontal scale, schema‑flexible MongoDB/Couchbase
Write‑heavy, TTL Redis
Analytics ClickHouse, BigQuery

 

3.1  Memory Management & Performance

Action Detail / Tool
Avoid needless allocations Reuse buffers (sync.Pool), stream large payloads (io.Reader).
Understand escape analysis go build -gcflags=”-m” shows heap vs stack decisions.
Profile early pprof, go tool trace, allocs/op in benchmarks.
GC tuning (rare) GOGC, SetGCPercent—only after measuring.

3.2  Database Handling

  • Use connection pooling (database/sql handles this; set MaxOpenConns, MaxIdleConns, ConnMaxLifetime).
  • Prefer prepared statements / ORM (sqlc, gorm, bun) to prevent SQL injection.
  • Migrations: golang-migrate, goose.
  • Wrap DB calls with context + timeout.

3.3  Error & Panic Strategy

Layer Approach
Library Return error, never panic.
Service Central middleware to translate errors → HTTP / gRPC codes.
Logging Wrap with %w (Go 1.13) for call‑site context.
Recovery Gin/Fiber middlewares or custom defer func() { if r := recover() … }.

3.4  Logging & Observability

  • Structured logging: uber-go/zap, rs/zerolog.
  • Metrics: prometheus/client_golang, histogram for latency, counter for errors.
  • Tracing: OpenTelemetry (go.opentelemetry.io/otel).
  • Health checks: /healthz, /readyz, plus DB ping.

3.5  Testing

Test Type Tool / Tip
Unit Table‑driven tests, go test -run
Integration Spin up real DB with testcontainers‑go
Benchmarks go test -bench ., compare with benchstat
Fuzzing go test -fuzz (since Go 1.18)

4  Infrastructure & Deployment

Area Recommendation
Dependency management go mod tidy, use semantic‑version tags.
CI/CD golangci-lint, go vet, govulncheck -> build -> unit tests -> Docker image.
Containerization Multi‑stage Dockerfile (scratch or distroless) for tiny images.
Runtime configuration 12‑factor: env vars parsed via spf13/viper or koanf.
Secrets Vault, AWS Secrets Manager; never bake into images.
Kubernetes Readiness/liveness probes, resource limits, HPA based on custom Prometheus metrics.
Rollback Blue/Green or Canary via Argo Rollouts or Flux.

5  Security & Compliance

  1. Transport security – TLS everywhere (autocert, ALB termination, or mesh).
  2. AuthN/Z – JWT for stateless APIs, OAuth2 for external, mTLS for internal gRPC.
  3. Static analysis – gosec, staticcheck.
  4. Input validation – go-playground/validator, sanitize before DB.
  5. Data retention & encryption – At‑rest (RDS, S3 SSE‑KMS) and in‑transit.

6  Operational Excellence

Concern Go‑Friendly Solutions
Graceful shutdown srv := &http.Server{} + signal.NotifyContext
Back‑pressure Buffered channels, worker pools, rate limiters (golang.org/x/time/rate).
Feature flags go-feature-flag, LaunchDarkly SDK.
Alerting Prometheus → Alertmanager → PagerDuty / Slack.
Documentation godoc, OpenAPI/Swagger UI, ADRs for key decisions.

Starter Skeleton Repo Layout (one suggestion)

csharp

CopyEdit

cmd/            // entry points (main packages)

internal/

app/        // business logic, service layer

db/         // SQL queries or repository layer

transport/

http/

grpc/

pkg/            // reusable libraries

configs/        // YAML/JSON defaults

scripts/        // CI, dev helpers

deploy/         // Helm charts, Terraform

44. What is diff between select and switch in Golang

Feature switch select
Used for Matching values Waiting on multiple channel operations
Works with Constants, expressions Channels only
Blocks? ❌ (non-blocking) ✅ (blocks if no case is ready)
Use case Control logic, condition handling Concurrency, goroutine coordination

x := 2

switch x {

case 1:

fmt.Println(“one”)

case 2:

fmt.Println(“two”)

default:

fmt.Println(“other”)}

✅ select – Channel-Based Multiplexing

Used to wait on multiple channels at once.

Example:

ch1 := make(chan string)

ch2 := make(chan string)

 

go func() { ch1 <- “from ch1” }()

go func() { ch2 <- “from ch2” }()

 

select {

case msg1 := <-ch1:

fmt.Println(“Received:”, msg1)

case msg2 := <-ch2:

fmt.Println(“Received:”, msg2)

default:

fmt.Println(“No channel ready”)

}

45. what is channels

In Go, channels are built-in features that let goroutines communicate with each other safely and synchronously.

They are a key part of Go’s concurrency model, enabling you to pass data between goroutines without using explicit locks or shared memory.

🔁 What is a Channel?

A channel is a pipe through which one goroutine can send data and another can receive it.

📦 Basic Syntax

ch := make(chan int) // creates an unbuffered channel of type int

🧠 How Channels Work

  • ch <- value — Send value to channel
  • value := <-ch — Receive value from channel
  • Communication blocks until the other side is ready
  • 🔀 Types of Channels
Type Description Example
Unbuffered Sends block until receiver receives make(chan int)
Buffered Allows sending without immediate receive make(chan int, 5)
Receive-only Channel that can only be read var ch <-chan int
Send-only Channel that can only be written to var ch chan<- int

46.Why use mutex

Because Go is concurrent, and shared variables can be accessed simultaneously by multiple goroutines — which causes race conditions, inconsistent data, or even crashes.

A mutex ensures that only one goroutine can access a particular section of code (called a critical section) at a time.

 

🔁 When Should You Use a Mutex?

Use a mutex when:

  • You are accessing or modifying shared variables (global or heap) from multiple goroutines
  • You want to synchronize access to a critical section

⚠️ What Happens Without a Mutex?

  • Race conditions: Multiple goroutines try to read/write at the same time
  • Inconsistent state: One goroutine sees half-written data
  • Unpredictable bugs: Very hard to reproduce and debug

📚 Go Mutex API (in sync package)

Function Purpose
mu.Lock() Blocks if already locked
mu.Unlock() Releases the lock
mu.TryLock() (Go 1.18+) Attempts non-blocking lock
sync.RWMutex Allows multiple readers, one writer

 

47.why use lock and unlock

Because Go programs are concurrent — multiple goroutines may try to read/write shared variables at the same time. Without synchronization, this causes:

  • Race conditions
  • Data corruption
  • Unpredictable bugs

Lock() and Unlock() ensure that only one goroutine at a time can access the critical section (the shared resource).

Real Example: Counter Update

❌ Without Lock (Race Condition)

var count int

 func increment() {

    for i := 0; i < 1000; i++ {

        count++ // Not thread-safe!

    }

}

If two goroutines call increment(), they might both read and write count at the same time, leading to wrong results.

✅ With Lock (Safe)

go

CopyEdit

var (

    count int

    mu    sync.Mutex

)

 func increment() {

    for i := 0; i < 1000; i++ {

        mu.Lock()      // Acquire lock

        count++        // Critical section

        mu.Unlock()    // Release lock

    }

}

  • mu.Lock() blocks other goroutines until the lock is available.
  • mu.Unlock() releases the lock so the next goroutine can enter.

⚙️ When to Use Lock/Unlock?

Use it whenever shared data is being modified or read by multiple goroutines.

Common cases:

  • Shared counters or state
  • Writing to a map or slice
  • Reading & writing to files
  • Managing shared cache

⚠️ Important Notes

Rule Why it matters
Always call Unlock() after Lock() Or you may deadlock the program
Use defer mu.Unlock() Ensures unlock even if a panic or return occurs
Only lock what you need Keep the locked section small for performance

🧪 Example with defer

mu.Lock()

defer mu.Unlock()

 // safe code here

This ensures Unlock() will always run, even if your function panics or returns early.

🧠 Summary

Concept Meaning
Lock() Waits until it can access safely
Unlock() Releases the lock
Race Condition Bug caused by unsynchronized access

⚠️ What Happens If You Use Lock but Not Unlock

If you Lock() but forget to Unlock(), your program may:

  • Deadlock – the goroutine never releases the lock, and others get stuck waiting forever.
  • Block indefinitely – if you’re using WaitGroup or select, the program may hang.
  • Lock() acquires the mutex. If another goroutine already holds it, the current one waits (blocks).
  • Unlock() releases the mutex, allowing another waiting goroutine to proceed.

48. what is race condition

A race condition in programming occurs when two or more goroutines (or threads) access shared data at the same time, and at least one of them writes to it, leading to unexpected behavior or incorrect results.

49. what is diff between array and slice

Array A fixed-size sequence of elements of the same type. Size is part of its type.
Slice A dynamically-sized, flexible view into an array. Backed by an underlying array.

🔍 Key Differences Between Array and Slice

Feature Array Slice
Size Fixed at compile-time ([3]int) Dynamic, can grow/shrink ([]int)
Syntax var a [3]int var s []int
Flexibility Rigid and less used Very flexible, commonly used
Memory Stored inline in memory References an underlying array
Passing to func Passed by value (copy) Passed by reference (pointer-like)
Can grow? ❌ No ✅ Yes (with append())
Default value Zero values nil slice by default

50.what is diff between concurrency and parallelism

Concept Concurrency Parallelism
Definition Managing multiple tasks at the same time (can switch between them) Executing multiple tasks at the same time (on multiple CPUs)
Goal Structure & responsiveness Speed & performance
How it works Tasks take turns (interleaved execution) Tasks run truly simultaneously
Analogy One chef cooking many dishes by switching tasks Multiple chefs cooking dishes at once

  Concurrency = multiple goroutines scheduled by the Go runtime

  Parallelism = goroutines run on multiple OS threads on multiple CPU cores

Feature Description
goroutines Enable concurrency
GOMAXPROCS Controls number of threads/CPU cores used (controls parallelism)
sync.WaitGroup, channels Help coordinate concurrent tasks
Key Point Concurrency Parallelism
Multiple tasks
At the same time ❌ (interleaved) ✅ (truly simultaneous)
Needs multiple cores
Achieved with Go ✅ via goroutines ✅ with goroutines + cores

 

51. Difference between rune and string.

Feature string rune
Type Immutable []byte (UTF-8) int32, represents one character
Length Number of bytes (len(str)) Use []rune(str) to get characters
Purpose Full text Single character / Unicode code point
Mutable? ❌ immutable ✅ can modify individual runes
Useful for Sentences, names, etc. Character processing, Unicode logic

When to Use What

Task Use
Store or pass text string
Work with individual characters rune
Count characters in text []rune(str)
Manipulate characters (e.g., case) rune

52.What is middleware

In Golang, particularly when building web applications or APIs (e.g., using frameworks like Fiber, Gin, Echo, or even plain net/http),
a middleware is a function that runs before (or sometimes after) your actual request handler to process or modify the incoming request and/or outgoing response.

Key Idea

Middleware acts like a layer or filter in your application’s request-response cycle.
It is often used for things like:

  • Logging requests
  • Authentication & authorization
  • Request validation
  • Adding CORS headers
  • Rate limiting
  • Compressing responses

Middleware in Go is just a function that wraps another handler, allowing you to intercept requests and responses for things like security, logging, and validation.

 53. What is wrapper function

In Golang, a wrapper function is a function that is designed to “wrap” another function or piece of logic.
It’s mainly used to add extra behavior before, after, or around the execution of the original function — without modifying that original function’s code.

Go does not have wrapper classes like Java, but we achieve similar functionality using structs, interfaces, and composition. A wrapper in Go typically embeds another type and adds additional behavior such as logging, validation, or transformation. This is similar to the decorator pattern.

Why use wrapper functions?

  • Code reuse → You can reuse the extra logic across multiple functions.
  • Separation of concerns → Keep your core logic clean and put logging, error handling, or pre/post-processing in the wrapper.
  • Wrapper functions usually return another function.
  • Commonly used for logging, authentication checks, timing, or retries.
  • In HTTP servers (like Fiber, Gin), middleware is often implemented as a type of wrapper function.

54.What is grpc in Golang

  • WHY IT IS USED
  • High-performance RPC using HTTP/2
  • Uses Protocol Buffers
  • Use when:
  • Low latency required
  • Internal microservices communication.

In Go, gRPC is a high-performance, open-source Remote Procedure Call (RPC) framework developed by Google that allows different services (possibly in different languages) to communicate with each other efficiently.

It uses Protocol Buffers (protobuf) as the interface definition language (IDL) for defining services and messages.

Key Features of gRPC in Golang

  1. Language-agnostic – You can write one service in Go, another in Java, Python, etc., and they can talk to each other.
  2. HTTP/2 based – Supports multiplexing, streaming, and better performance than HTTP/1.1.
  3. Strongly Typed Contracts – Uses .proto files to define message structures and service methods.
  4. Automatic Code Generation – You define your service once in .proto, then use protoc to generate Go code for server and client.
  5. Streaming Support – gRPC supports:
    • Unary RPC (single request, single response)
    • Server streaming (single request, multiple responses)
    • Client streaming (multiple requests, single response)
    • Bidirectional streaming (multiple requests & responses)
  6. Efficient Serialization – Protobuf messages are binary and compact, making them faster than JSON.

55. What is RabbitMQ

RabbitMQ is an open-source message broker that allows different services, applications, or components to communicate with each other by sending and receiving messages asynchronously.

📌 How It Works

  • Producer → sends messages to RabbitMQ.
  • RabbitMQ stores them in a queue.
  • Consumer → retrieves and processes messages from the queue.

⚡ Why Use RabbitMQ?

  • Decouples services (services don’t call each other directly).
  • Handles asynchronous processing.
  • Can buffer requests when consumers are slow.
  • Provides reliability (messages won’t be lost if a consumer is down).
  • Supports multiple messaging patterns like Pub/Sub, Work Queues, Routing, Topics.

🛠 Example Use Cases

  • Sending emails in the background.
  • Processing heavy tasks (image/video processing) without blocking API calls.
  • Microservices communication.
  • Real-time notifications.

56. If i create 2 reciver channels for diff goroutine is it work?

  • Yes, you can create two receiver channels for different goroutines in Go, and it will work — as long as each channel is being read by only one goroutine at a time.
  • Here’s the key points you should keep in mind:
  • 1️ Separate channels for different goroutines
  • If you create two different channels and assign each to a separate goroutine, they will work independently without interfering with each other.
    2️ One channel, multiple receivers
  • If you have one channel and multiple goroutines are reading from it, Go will distribute messages among them (like load balancing). Only one receiver gets each message.

     3️ Multiple receivers for same data

If you want both receivers to get the same data, channels won’t do that by default — you’d need to fan out the message (send copies) or use something like a sync.Mutex + shared variable, or a pub/sub pattern.

57. What is Kafka why it is used

Apache Kafka is an open-source distributed event streaming platform used to handle real-time data pipelines and stream processing at scale.

Think of it like a high-performance postal service for data — you have producers sending messages, Kafka delivering them reliably, and consumers picking them up whenever they’re ready.

Why Kafka is Used

Kafka is mainly used when you need high-throughput, fault-tolerant, and scalable systems for handling streams of data.

Key Uses

  1. Real-time data streaming
    • Streaming logs, metrics, transactions, or sensor data in real-time.
  2. Event-driven architecture
    • Microservices can communicate asynchronously via events.
  3. Data integration
    • Acts as a bridge between different systems (e.g., MySQL → Kafka → Elasticsearch).
  4. Log aggregation
    • Centralizes logs from different applications/servers.
  5. Analytics and monitoring
    • Processes and analyzes data as it arrives.

How Kafka Works

  • Producer → sends messages to Kafka.
  • Kafka broker → stores messages in topics.
  • Consumer → reads messages from topics.
  • Messages are stored in partitions for scalability and parallel processing.
  • Kafka retains messages for a configurable time, so consumers can replay them.

Apache Kafka is an open-source distributed event streaming platform used to handle real-time data pipelines and stream processing at scale.

Think of it like a high-performance postal service for data — you have producers sending messages, Kafka delivering them reliably, and consumers picking them up whenever they’re ready.

Why Kafka is Used

Kafka is mainly used when you need high-throughput, fault-tolerant, and scalable systems for handling streams of data.

Key Uses

  1. Real-time data streaming
    • Streaming logs, metrics, transactions, or sensor data in real-time.
  2. Event-driven architecture
    • Microservices can communicate asynchronously via events.
  3. Data integration
    • Acts as a bridge between different systems (e.g., MySQL → Kafka → Elasticsearch).
  4. Log aggregation
    • Centralizes logs from different applications/servers.
  5. Analytics and monitoring
    • Processes and analyzes data as it arrives.

How Kafka Works

  • Producer → sends messages to Kafka.
  • Kafka broker → stores messages in topics.
  • Consumer → reads messages from topics.
  • Messages are stored in partitions for scalability and parallel processing.
  • Kafka retains messages for a configurable time, so consumers can replay them.

58. what is cors

CORS stands for Cross-Origin Resource Sharing — it’s a security mechanism built into web browsers that controls whether a web page can request resources (like APIs, images, fonts) from a different origin than the one it was loaded from.

Key Idea

  • Origin = combination of protocol, domain, and port.
    Example:
  • By default, browsers block cross-origin requests to protect users from malicious sites.
  • CORS is a way for the server to tell the browser,
    “It’s okay to load this resource from another origin.”

How It Works

  1. Browser sends a request (sometimes a “preflight” OPTIONS request first) to the server.
  2. Server responds with special HTTP headers like:

 

Access-Control-Allow-Origin: https://myfrontend.com

Access-Control-Allow-Methods: GET, POST

Access-Control-Allow-Headers: Content-Type

  1. If the headers match the browser’s expectations, the browser allows the request.

Why It’s Used

  • To allow safe communication between frontend (on one domain) and backend (on another domain).
  • To prevent malicious websites from making unauthorized requests on behalf of a user.

59.What we used security purpose for rest Api

For securing a REST API in Golang (or any backend), you typically combine multiple security mechanisms, since there’s no single “one-size-fits-all” method.
Here’s a structured breakdown:

  1. Authentication (Who you are)
  • JWT (JSON Web Token) — Common for stateless authentication.
  • OAuth 2.0 — Used when integrating with third-party logins (Google, GitHub).
  • API Keys — For simple service-to-service authentication.
  • Basic Auth — Very simple, but generally avoided for production unless over HTTPS.
  1. Authorization (What you can do)
  • Role-Based Access Control (RBAC) — Example: Admin, User, Assessor, Requestor.
  • Attribute-Based Access Control (ABAC) — More fine-grained based on user attributes.
  1. Transport Security
  • HTTPS/TLS — Encrypts data in transit to prevent sniffing or MITM attacks.
  1. Input Validation & Sanitization
  • Validate request body, query params, headers, and URL inputs.
  • Use proper types, regex, or libraries to prevent SQL injection and XSS.
  1. CORS Protection
  • Configure allowed origins, methods, and headers to prevent unauthorized cross-domain requests.
  1. Rate Limiting & Throttling
  • Prevents brute force attacks and API abuse.
  • Example libraries: golang.org/x/time/rate, or reverse proxy level with Nginx/Cloudflare.
  1. Logging & Monitoring
  • Log requests, authentication failures, and unusual activity.
  • Use tools like Prometheus, Grafana, or ELK stack for monitoring.
  1. Data Protection
  • Store passwords hashed with bcrypt/argon2.
  • Avoid storing sensitive data in plaintext (e.g., use encryption at rest).
  1. Middleware-Based Security

In Gin or Fiber, you can add middleware for:

  • Authentication check before hitting the main handler.
  • Request validation.
  • Error recovery to avoid leaking stack traces.

Example (Gin JWT middleware):

func AuthMiddleware() gin.HandlerFunc {

return func(c *gin.Context) {

token := c.GetHeader(“Authorization”)

if !ValidateJWT(token) {

c.JSON(http.StatusUnauthorized, gin.H{“error”: “Unauthorized”})

c.Abort()

return

}

c.Next()

}

}

Best Practice → Use multiple layers together:
HTTPS + JWT/OAuth + RBAC + Rate Limiting + Input Validation + Logging.

60.what is monolithic and microservice application what is diff between them.

A monolithic application and a microservice application are two different ways to structure software architecture.

Monolithic Application

  • Definition:
    A single, unified application where all components (UI, business logic, database access, etc.) are packaged and deployed together.
  • Example:
  • A single .jar, .war, or binary file containing the whole system.
  • Characteristics:
    • One codebase, one deployment unit.
    • All modules share the same memory and database.
    • Scaling requires deploying the whole app again.
    • Tight coupling between components.

Microservice Application

  • Definition:
    An application is split into multiple small, independent services, each responsible for a specific business function.
  • Example:
    An e-commerce site where “Order Service,” “Payment Service,” and “Inventory Service” are separate deployable services.
  • Characteristics:
    • Each service has its own codebase, database, and deployment.
    • Services communicate via APIs (REST, gRPC, Kafka, RabbitMQ, etc.).
    • Easy to scale individual services.
    • Loose coupling and independent deployment.

Key Differences Between Monolithic and Microservices

Aspect Monolithic Microservices
Codebase Single Multiple (per service)
Deployment One deployment for entire app Independent deployment per service
Scalability Whole app scales together Scale individual services
Database Usually one shared database Each service can have its own DB
Coupling Tightly coupled Loosely coupled
Technology Stack Usually one Can be different for each service
Fault Isolation A bug can crash the whole app A bug affects only that service
Development Speed Slower for large teams Faster with small teams per service
Complexity Simple to start but harder to maintain at scale More complex to start but easier to maintain at scale

61. What is callback function

A callback function is a function that is passed as an argument to another function and is intended to be executed later, usually after some task is completed.

It’s a way to tell a function,

“When you’re done, call this function for me.”

🔹 In Golang

Go supports callbacks by passing function variables around.

Example:

package main

import “fmt”

// This function takes another function as an argument

func processData(data string, callback func(string)) {

fmt.Println(“Processing:”, data)

callback(data) // Call the callback after processing

}

// Callback function

func printResult(result string) {

fmt.Println(“Processed result:”, result)

}

func main() {

processData(“Hello Golang”, printResult)

}

📌 Why use callbacks?

  1. Asynchronous handling – e.g., run a function after data is fetched or a task finishes.
  2. Code flexibility – behavior can change depending on which callback is passed.
  3. Separation of concerns – processing logic and “what to do next” are separated.

62.What is polymorphism how to achieve in Golang using interface

Polymorphism is an object-oriented programming concept where different types can be accessed through the same interface, and each type can provide its own implementation of the behavior.

In simple terms:

The same action (method call) can behave differently depending on the object that is calling it.

🔹 How Polymorphism Works in Go

Go doesn’t have classes, but it supports polymorphism through interfaces.
If a type implements all the methods of an interface, it implicitly satisfies that interface — no explicit “implements” keyword is needed.

Key Points in Go’s Polymorphism:

  1. No inheritance — just interfaces and struct methods.
  2. Implicit implementation — no implements keyword.

Dynamic behavior — method execution depends on the actual type at runtime.

63.What is sweep & mark in garbage collection in Golang

Go’s GC is mark-and-sweep based.

  • Mark phase → The GC finds all objects that are still reachable (in use) and marks them.
  • Sweep phase → The GC goes through the heap and frees memory occupied by unmarked (unreachable) objects, making that memory available for future allocations.

Think of it like cleaning your desk:

  1. Mark: Tag the papers you still need.
  2. Sweep: Throw away the untagged ones.

📌 In Go:

  • Sweep doesn’t compact memory (no moving objects around).
  • Freed memory is put back into Go’s internal memory allocator for reuse.

2️⃣ make in Go

make is not part of garbage collection — it’s a built-in function used to allocate and initialize certain built-in data types:

  • slices
  • maps
  • channels

Unlike new (which only allocates memory), make also:

  • Sets up internal data structures (like slice headers, hash tables for maps, or channel buffers).
  • Returns a value ready to use.

How They Relate

  • Sweep → Happens automatically in GC to reclaim unused memory.
  • make → Explicitly called by your code to allocate and initialize special Go data structures.
  • After you stop using what you made (e.g., slice, map, channel) and no references remain, GC will mark it unused and sweep it away in future cycles.

64. What is a Closure Function in Go?

A closure is a function that captures variables from the scope where it was defined, and keeps them alive even after that scope has ended.

It’s basically:

“A function with a memory — it remembers the variables from the place it was born.”

Example of a Closure

package main

 import “fmt”

 func counter() func() int {

    count := 0

    return func() int {

        count++

        return count

    }

}

 func main() {

    c1 := counter()

    fmt.Println(c1()) // 1

    fmt.Println(c1()) // 2

    fmt.Println(c1()) // 3

 

    c2 := counter()

    fmt.Println(c2()) // 1  (separate memory)

}

Key Points:

  • The inner function remembers count from the outer function’s scope.
  • Even though counter() finished, count still lives because the closure keeps it alive.

65.What are Generics in Go?

  • Generics allow you to write functions and data structures that work with different types while keeping type safety.
  • Before Go 1.18, developers used interface{} (or any) to achieve type flexibility, but it lost compile-time type safety.
  • With generics, you can parameterize types using type parameters (like templates in C++ or generics in Java).

🔹 Which version introduced Generics?

👉 Generics were introduced in Go 1.18 (released in March 2022).

Key Points

  • Introduced in Go 1.18.
  • Uses type parameters in square brackets [T any].
  • Supports constraints (int | float64 or custom interfaces).
  • Increases code reusability with type safety.

66.Can we pass parameters to main() in Go?

  • In Go, the main() function cannot accept parameters

func main() {

// os.Args holds all command-line arguments

fmt.Println(“All args:”, os.Args)

if len(os.Args) > 1 {

fmt.Println(“First arg:”, os.Args[1])

}

}
go run main.go hello world

O/p

All args: [main hello world]

First arg: hello

os.Args[0] → program name (e.g., main).

os.Args[1:] → actual command-line parameters.

You can pass any number of parameters.

67. How to Avoid Memory Leaks in Go

  • pprof
  • Monitor goroutines
  • Check unclosed channels

Close Goroutines Properly

  • If a goroutine is waiting forever (e.g., on a channel that never sends), it leaks.
    ✅ Always provide a way to stop goroutines using context cancellation or done channels.

Close Channels

  • Unclosed channels may cause blocked senders/receivers → memory leak.
    ✅ Close channels when no longer needed.

Avoid Holding References Unnecessarily

  • If a large object is stored in a global variable or slice but no longer needed, it prevents GC.
    ✅ Set it to nil when done.

Use defer to Release Resources

  • Files, DB connections, network sockets → always close them.

Question: What is Composition in Go?

  • Composition is a way to combine behaviors by embedding one struct inside another.
  • Instead of inheritance (“is-a” relationship), Go uses composition (“has-a” relationship).
  • It allows code reuse without a rigid class hierarchy.

Key Points for Interview

  1. Go does not support inheritance → uses composition.
  2. Composition is done via struct embedding.
  3. Promotes “has-a” relationship instead of “is-a”.
  4. Helps in code reuse and flexible design.

68. What is composition in Go?

Composition in Go is achieved by embedding structs or interfaces within other structs, enabling code reuse and polymorphic behavior without inheritance.

  • Question: Why Use Empty Struct in Go?
    Empty struct (struct{}) takes 0 bytes of memory.
  • Uses:
    1. As a map value for sets.
    2. As a signal in channels.
    3. As a placeholder type.
    4. In concurrency utilities for efficiency.

👉 So if asked: “Why use empty struct in Go?”
✅ Answer: Because it has zero size, making it memory-efficient for cases where only presence or signaling matters, not the actual data.

Example:

Strings = [“sumita”, “amit”, “mahesh”]

Output = [“m”, “a”]

Here’s a working Go program:

package main

import (

“fmt”

“strings”

)

func commonChars(words []string) []string {

if len(words) == 0 {

return []string{}

}

// Take first word as base

common := make(map[rune]int)

for _, ch := range words[0] {

common[ch]++

}

// Compare with each next word

for _, word := range words[1:] {

temp := make(map[rune]int)

for _, ch := range word {

if common[ch] > 0 {

temp[ch]++

if temp[ch] > common[ch] {

temp[ch] = common[ch]

}

}

}

common = temp

}

// Collect results

var result []string

for ch, count := range common {

for i := 0; i < count; i++ {

result = append(result, string(ch))

}

}

return result

}

func main() {

words := []string{“sumita”, “amit”, “mahesh”}

result := commonChars(words)

fmt.Println(result) // [“m”, “a”]

}

69.What is reflection in Golang

Go provides reflection through the reflect package.

. Why Reflection?

Normally in Go, types are known at compile time. But sometimes you want to:

  • Inspect an unknown type at runtime (e.g., in a JSON library, ORM like GORM, or serialization).
  • Dynamically access struct fields, methods, or values.
  • Write generic utilities (like logging, validation, data mapping).

🔹 Key Concepts in reflect

  1. reflect.TypeOf(i) → returns the type of a variable.
  2. reflect.ValueOf(i) → returns the value of a variable.
  1. Kind → the underlying category (int, string, slice, struct, etc.).
  2. Set → you can change values if the reflect.Value is addressable and exported.

70. How to set limit for goroutine in project

In Go, goroutines are lightweight, but unlimited spawning can overload memory/CPU.    So, we often set a limit (worker pool pattern) to control concurrency.

Here are common ways to do it:

🔹 1. Use a Buffered Channel as a Semaphore

  1. Worker Pool Pattern
     Small projects / simple APIs → Use semaphore (channel).

  Batch processing / pipelines → Use worker pool.

  Structured concurrency → Use errgroup with SetLimit().

71. What is pointer

In Go, a pointer is a variable that stores the memory address of another variable.
Instead of holding the actual value, it points to where that value is stored in memory.

🔹 Basics

  • A pointer type is written with *T, where T is the type it points to.
  • The address-of operator (&) is used to get the memory address of a variable.
  • The dereference operator (*) is used to access the value stored at that address.

Example

package main

import “fmt”

func main() {

x := 10        // normal integer variable

p := &x        // p is a pointer to x (type *int)

fmt.Println(“x =”, x)      // 10

fmt.Println(“p =”, p)      // memory address of x

fmt.Println(“*p =”, *p)    // value at that memory address (10)

// change value using pointer

*p = 20

fmt.Println(“x after change =”, x) // 20

}

72.What is GOROOT in Go?

  • GOROOT is an environment variable in Go that tells your system where the Go SDK (compiler, tools, standard library) is installed.

In simple words: it’s the root directory of the Go installation.

73.what is wrap & unwrap error

 

In Go 1.13+, the standard library introduced error wrapping and unwrapping so you can attach extra context to errors while still keeping track of the original cause.
Wrapping Errors

When you return an error, you can wrap it with more context using fmt.Errorf and the special %w verb.

package main

 import (

“errors”

“fmt”

)

var ErrNotFound = errors.New(“record not found”)

func findUser(id int) error {

if id == 0 {

return ErrNotFound

}

return nil

}

func getUser(id int) error {

if err := findUser(id); err != nil {

// wrap the original error with more context

return fmt.Errorf(“getUser failed: %w”, err)

}

return nil

}

func main() {

err := getUser(0)

fmt.Println(“Error:”, err) // Error: getUser failed: record not found

}

Here:

  • %w wraps the original error inside the new one.
  • The caller sees the context + the original root error.

🔹 Unwrapping Errors

You can unwrap errors using the errors package:

  1. errors.Is(err, target)
    Checks if the error or any wrapped error is target.

if errors.Is(err, ErrNotFound) {

fmt.Println(“User not found!”)

}

  1. errors.As(err, &targetType)
    Extracts the original error into a variable if it matches a type.

var pathErr *os.PathError

if errors.As(err, &pathErr) {

fmt.Println(“Path error on file:”, pathErr.Path)

}

  1. errors.Unwrap(err)
    Returns the next error in the chain (unwraps one layer).

cause := errors.Unwrap(err)

fmt.Println(“Root cause:”, cause) // Root cause: record not found

🔹 Why use Wrap & Unwrap?

  • Add context without losing the original error.
  • Helps in debugging (you know where the error happened and why).
  • Makes error handling more powerful with errors.Is / errors.As.

✅ In short:

  • Wrap = Add context to an error (fmt.Errorf(“… %w”, err)).
  • Unwrap = Retrieve or check the original error (errors.Unwrap, errors.Is, errors.As).

74. Using Oauth third party Api access only some users how can we done in Golang

  1. Users log in with a third-party provider (Google, GitHub, etc.) via OAuth2.
  2. Your Go backend receives the access token (or ID token) from the provider.
  3. You verify the token and extract user info (like email, user ID).
  4. You check the user against your own allowlist (DB, config, or role table).
  5. If allowed → issue your own JWT/session → grant access.
  6. If not allowed → deny access.

🔹 2. Go Libraries to Use

  • golang.org/x/oauth2 → standard OAuth2 client.
  • github.com/coreos/go-oidc → if you need to verify OpenID Connect (ID tokens, e.g., Google).
  1. What client ID / client secret mean
  • When you register your app with a third-party provider (Google, GitHub, Zoho, etc.), they give you:
    • Client ID → identifies your app.
    • Client Secret → used to prove your app’s authenticity.
  • Your Go service uses these to request tokens on behalf of a user.

🔹 2. OAuth Flow (with client ID & secret)

  1. User Login Redirect
    • Your app redirects user to the third-party OAuth authorization URL (with client ID).
  2. User Authorizes
    • User logs in and grants permission.
  3. Token Exchange
    • The provider redirects back with a code.
    • Your backend exchanges that code for an access token using client ID + client secret.
  4. User Info Fetch
    • You call the provider’s /userinfo (or similar) API with the access token to get user details (email, id, etc.).
  5. Restrict Access
    • You check if the user is allowed (via DB/allowlist). If yes → issue your own token/session.

75.Call multiple goroutines directly in the main() function — each one doing a separate task concurrently.

Here’s a clean and production-style example showing how to call multiple goroutines safely and properly from main() using sync.WaitGroup.

✅ Example — Multiple Goroutines in main()

package main

import (

“fmt”

“sync”

“time”

)

 

// simulateTask simulates a time-consuming task

func simulateTask(name string, delay time.Duration, wg *sync.WaitGroup) {

defer wg.Done() // mark this goroutine as done when finished

for i := 1; i <= 3; i++ {

fmt.Printf(“%s working… step %d\n”, name, i)

time.Sleep(delay)

}

fmt.Printf(“%s completed ✅\n”, name)

}

func main() {

var wg sync.WaitGroup

// Launch multiple goroutines

wg.Add(1)

go simulateTask(“Task 1”, 500*time.Millisecond, &wg)

wg.Add(1)

go simulateTask(“Task 2”, 300*time.Millisecond, &wg)

wg.Add(1)

go simulateTask(“Task 3”, 700*time.Millisecond, &wg)

wg.Add(1)

go simulateTask(“Task 4”, 400*time.Millisecond, &wg)

// Wait for all goroutines to finish

wg.Wait()

fmt.Println(“🎉 All tasks finished. Exiting main.”)

}

76.How to achive parallelism in golang using Parallel Computation

package main

import (

“fmt”

“runtime”

“sync”

“time”

)

func compute(id int, wg *sync.WaitGroup) {

defer wg.Done()

fmt.Printf(“Goroutine %d started on CPU %d\n”, id, runtime.NumCPU())

sum := 0

for i := 0; i < 100000000; i++ {

sum += i

}

fmt.Printf(“Goroutine %d done: Sum=%d\n”, id, sum)

}

func main() {

// Use all CPU cores available

numCPU := runtime.NumCPU()

runtime.GOMAXPROCS(numCPU)

fmt.Printf(“Running with %d CPUs\n”, numCPU)

 

var wg sync.WaitGroup

start := time.Now()

 

// Launch multiple goroutines in parallel

for i := 1; i <= numCPU; i++ {

wg.Add(1)

go compute(i, &wg)

}

 

wg.Wait()

fmt.Printf(“✅ All done in %v\n”, time.Since(start))

}

Parallelism with Worker Pool Example

package main

 

import (

“fmt”

“runtime”

“sync”

)

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

defer wg.Done()

for j := range jobs {

fmt.Printf(“Worker %d processing job %d\n”, id, j)

}

}

func main() {

runtime.GOMAXPROCS(runtime.NumCPU())

jobs := make(chan int, 10)

var wg sync.WaitGroup

 

for w := 1; w <= 4; w++ {

wg.Add(1)

go worker(w, jobs, &wg)

}

 

for j := 1; j <= 8; j++ {

jobs <- j

}

close(jobs)

wg.Wait()

}

Here, 4 workers handle 8 jobs in parallel across CPU cores.

✅ Summary

Feature Use
go func() Runs goroutine concurrently
runtime.NumCPU() Finds number of CPU cores
runtime.GOMAXPROCS(n) Enables parallel execution on n cores
sync.WaitGroup Waits for goroutines to complete
Parallelism achieved when multiple goroutines actually run on multiple CPU cores

77. Authentication comes first or Authorization

Authentication comes first, then Authorization.

🔑 Why?

Step Meaning Question it answers
Authentication Verifies who the user is “Are you really this user?”
Authorization Verifies what the user is allowed to do “What permissions do you have?”

🔄 Order in real flow

  1. User logs in with username/password (Authentication)
  2. System confirms identity → generates token/session
  3. System checks user roles/permissions (Authorization)
  4. User is allowed or denied access to the requested feature

📌 Real-world analogy

Daily Life Example
At office gate: Security checks ID → Authentication
In the office building: Access card decides which floors/rooms you can enter → Authorization

🔥 One-line answer

Authentication always comes before Authorization.

Because system cannot decide what a user can access until it knows who the user is.

78. What is 401 api response

Unauthorized – the request has not been applied because it lacks valid authentication credentials.

You will usually receive HTTP 401 when:

  • No token is sent
  • Token is expired
  • Token is invalid or malformed
  • Wrong username/password
  • Authorization header missing

💡 Example of 401 response

HTTP/1.1 401 Unauthorized

{

“error”: “Unauthorized”,

“message”: “Invalid or missing token”

}

⚠ 401 vs 403 (important difference)

Status Meaning Cause
401 Unauthorized Authentication failed User is not logged in or token is invalid
403 Forbidden Authorization failed User is logged in but doesn’t have permission

✔ How to fix 401

Problem Solution
Token not sent Add Authorization: Bearer <token> in header
Token expired Refresh token / login again
Invalid token Re-generate token
Wrong credentials Correct username/password

79.What code practice need to follow in Golang

Follow Go Naming Conventions

Type Convention Example
Package lower case, no underscore package userauth
Variable / Function camelCase totalCount, getUserData()
Exported Name PascalCase GetUser()
Constants UPPER_SNAKE_CASE (or PascalCase) MAX_RETRY, DefaultLimit

✅ 2. Use gofmt Formatting

Always format your code:

go fmt ./…

Go prefers tabs over spaces, automatic alignment, and clean formatting.

✅ 3. Keep Functions Small

A function should do one task only.
Bad:

func ProcessOrder() { /* 100s of lines */ }

Good:

func ValidateOrder() {}

func SaveOrder() {}

func SendOrderEmail() {}

✅ 4. Error Handling Practices

  • Don’t ignore errors
  • Return early instead of nesting deeply

Bad:

if err != nil {

// …

} else {

// nested large logic

}

Good:

if err != nil {

return err

}

// continue

Use meaningful error messages:

return fmt.Errorf(“failed to connect DB: %w”, err)

✅ 5. Avoid Global Variables

Prefer dependency injection:

type Service struct {

db *sql.DB

}

func NewService(db *sql.DB) *Service { return &Service{db: db} }

✅ 6. Use Context for Request-Scoped Data

Especially for APIs / DB operations:

func GetUser(ctx context.Context, id int) {}

✅ 7. Keep Packages Small and Purposeful

Bad:

package utils  // used for everything

Good:

package logger

package validation

package repository

✅ 8. Write Unit Tests

Use testing package:

go test ./…

Test exported and critical functions.

✅ 9. Use Interfaces Only When Needed

Don’t create interfaces just for abstraction.
Use interfaces only when multiple implementations are expected.

✅ 10. Concurrency Safety

  • Use channels or mutex for shared memory
  • Avoid race conditions
  • Run tests with race detector:

go test -race ./…

Performance Practices

Do Avoid
Use slices over arrays Using large arrays
Use sync.Pool for reusable objects Allocating unnecessary memory
Use jsoniter for heavy JSON workloads Default JSON when performance critical
Use Goroutines for I/O-bound tasks Overspawning goroutines

80.What is use of Sonarqube

What SonarQube Does

SonarQube scans your source code and detects:

Category Examples
Bugs Null pointer issues, resource leaks
Vulnerabilities SQL Injection, XSS, hardcoded credentials
Code Smells Bad design, duplicated code, long functions
Test Coverage How much code is covered by unit tests
Maintainability Issues High complexity, unused variables, dead code
Security Hotspots Code needing review for security risk

Why SonarQube Is Used

Purpose Benefit
Improve code quality Cleaner & maintainable code
Detect vulnerabilities early Reduce security risk
Enforce coding standards Consistency across teams
Track technical debt Visibility of improvement areas
Continuous integration Automates scanning in pipelines (CI/CD)

🛠 Where SonarQube Is Used

  • Software development teams
  • DevOps CI/CD pipelines
  • Code review stages (PR scanning)
  • Agile projects to maintain long-term quality

💡 CI/CD Usage Example

SonarQube is integrated into:

  • Jenkins
  • GitHub Actions
  • GitLab CI/CD
  • Azure DevOps
  • Bitbucket Pipeline

It scans code after every commit / pull request and generates a quality report.

81.What is authorization

Authorization is the process of determining what an authenticated user is allowed to access or do.

🔑 Simple Definition

Authorization decides whether a user has permission to perform an action or access a resource.

It happens after authentication.

📌 Example

  1. Authentication → User logs in with username + password
  2. Authorization → System checks:
    • Can this user access the dashboard?
    • Can this user delete a record?
    • Can this user upload a file?

82. What is used of gorila mux lib in gin how the routing done

Framework Package Usage
Gorilla Mux github.com/gorilla/mux Router for net/http
Gin github.com/gin-gonic/gin Full web framework & router

🛑 Gorilla Mux is NOT used inside Gin.
They are separate libraries. You use either Gorilla Mux or Gin, not both together.

🔹 What is Gorilla Mux used for?

Gorilla Mux is a powerful HTTP router for Go (used with net/http).
It provides:

  • URL path parameters (/users/{id})
  • Query matching
  • Method matching (GET/POST/PUT)
  • Middleware support

✔ Example routing using Gorilla Mux

package main

 

import (

“fmt”

“net/http”

“github.com/gorilla/mux”

)

 

func main() {

r := mux.NewRouter()

 

r.HandleFunc(“/users/{id}”, func(w http.ResponseWriter, r *http.Request) {

params := mux.Vars(r)

fmt.Fprintf(w, “User ID: %s”, params[“id”])

}).Methods(“GET”)

 

http.ListenAndServe(“:8080”, r)

}

83. What is Gin used for?

Gin is a fast web framework with router + middleware + JSON handling.

✔ Example routing using Gin

package main

import “github.com/gin-gonic/gin”

func main() {

r := gin.Default()

r.GET(“/users/:id”, func(c *gin.Context) {

id := c.Param(“id”)

c.JSON(200, gin.H{“user_id”: id})

})

r.Run(“:8080”)

}

🔥 Key Difference in Routing Style

Feature Gorilla Mux Gin
Path parameter {id} :id
Response Manual fmt.Fprintf / json.NewEncoder c.JSON, c.String, etc.
Performance Slower Very fast
Framework Only router Full framework (router + middleware + binding)
Learning curve Simple Moderate

📝 When to use which

Use Gorilla Mux when Use Gin when
You want simple http routers You want a full web backend
You prefer net/http You need fast JSON APIs
Small/lightweight project REST API projects

84. What is diff between query and params

: Query parameters are sent after ? symbol in the URL and used for filtering, searching, sorting, pagination, etc.

URL example:

/users?role=admin&page=2

Key points

Feature Value
Part of URL After ?
Optional Yes
Used for Filters / search / sorting / pagination
Format key=value&key2=value2

Difference Summary

Feature Query Parameters Path Parameters
Location in URL After ? Inside route
Mandatory No Yes
Purpose Filters / search / optional inputs Identify a specific resource
Example /users?role=admin /users/10
Extract in Gin c.Query(“key”) c.Param(“key”)

85. How you have management cache in Golang

Use case

  • Single service instance
  • Fast reads
  • Data can be lost on restart
  • Never cache auth-sensitive data blindly
  • Cache read-heavy, not write-heavy data
  • Measure hit ratio

86. where you used mutex in Golang

mutex is used to protect shared data when multiple goroutines access it at the same time.
Without a mutex → race condition ❌
With a mutex → safe, predictable behavior ✅
Why mutex is needed (problem)

var count int

 

func increment() {

count++

}

If 100 goroutines call increment():

  • count++ is not atomic
  • Final value will be wrong

2️.Basic mutex usage

var (

count int

mu    sync.Mutex

)

func increment() {

mu.Lock()

count++

mu.Unlock()

}

✔ Only one goroutine modifies count at a time

3️. Where mutex is ACTUALLY used in real projects

✅ 1. Protect shared in-memory cache

type Cache struct {

data map[string]string

mu   sync.RWMutex

}

func (c *Cache) Get(key string) (string, bool) {

c.mu.RLock()

defer c.mu.RUnlock()

 

val, ok := c.data[key]

return val, ok

}

func (c *Cache) Set(key, value string) {

c.mu.Lock()

defer c.mu.Unlock()

 

c.data[key] = value

}

📌 Most common use-case

✅ 2. API request counters / metrics

type Metrics struct {

TotalRequests int

mu            sync.Mutex

}

func (m *Metrics) Inc() {

m.mu.Lock()

m.TotalRequests++

m.mu.Unlock()

}

✅ 3. Singleton initialization

var (

db   *sql.DB

once sync.Once

)

func GetDB() *sql.DB {

once.Do(func() {

db = connectDB()

})

return db

}

✔ Prevents multiple initializations

✅ 4. Worker pool shared state

type JobQueue struct {

jobs []string

mu   sync.Mutex

}

func (q *JobQueue) Add(job string) {

q.mu.Lock()

q.jobs = append(q.jobs, job)

q.mu.Unlock()

}

✅ 5. Session / token store

type SessionStore struct {

sessions map[string]string

mu       sync.Mutex

}

Used when:

  • In-memory auth sessions
  • OTP tracking
  • Rate limiting

4️.Mutex vs RWMutex (important)

Mutex RWMutex
One reader/writer Multiple readers
Slower reads Faster reads
Simple Best for read-heavy

var mu sync.RWMutex

mu.RLock()   // read

mu.RUnlock()

mu.Lock()    // write

mu.Unlock()

5️.When NOT to use mutex

❌ If only one goroutine accesses data
❌ If using channels already
❌ For DB-level concurrency (DB handles it)

6️.Mutex vs Channel (confusion point)

Mutex Channel
Protect shared memory Share memory
State protection Message passing
Low overhead Better for workflows

Rule of thumb:

Use mutex for data, channels for flow

Summary

You use mutex when:

  • Multiple goroutines access shared data
  • In-memory cache
  • Counters / metrics
  • Job queues
  • Rate limiters

Session storage

87. How to do authentication and authorization in Golang

Below is the standard, production-ready way to do Authentication & Authorization in Go, exactly how it’s done in real backend APIs (Gin/Fiber).

Authentication vs Authorization (first clear this)

Term Meaning
Authentication Who are you? (Login, token)
Authorization What are you allowed to do? (Roles, permissions)

👉 Authentication always comes first

Common Ways to Do Authentication in Go

  1. Basic Authentication (username + password in headers, rarely used in production)
  2. Session-Based Authentication (store session ID in cookies, typical for web apps)
  3. Token-Based Authentication (JWT, OAuth2, etc.) → widely used in APIs
  4. Third-party Authentication (Google, GitHub, etc. via OAuth2/OpenID Connect)
  1. JWT Authentication (Most Common for APIs)
  2. JWT (JSON Web Token) is a stateless token used for authenticating API requests.
  3. Create JWT Token
    Middleware to Validate Token
    . Usage in Routes

Authentication in Go (JWT-based – most common)

Flow

Login → Verify credentials → Generate JWT → Client sends JWT → Middleware validattes JWT

When to use what (important)

Scenario Solution
Simple API JWT
Microservices JWT + Redis
Enterprise OAuth2 / Keycloak
Mobile app JWT + Refresh token

  Authenticate → Login + JWT

  Authorize → Role/Permission middleware

  Protect routes → Middleware

  Secure passwords → bcrypt

  Always use HTTPS

88. What is 0 value in Golang

In Go (Golang), the zero value is the default value automatically assigned to a variable when it is declared without initialization.

Go always initializes variables — there are no uninitialized variables.

89. why use rebase in git

We use git rebase to clean up commit history and make it linear and easy to understand.

In short:

Rebase reapplies your commits on top of another branch as if they were written later.

“Peek” in Git (Informal Term ✅)

Peek means:

Quickly look at something without changing anything

It is a concept, not a Git command.

Common “peek” actions in Git:

1️.Peek at commit history

git log –oneline

2️.Peek at changes (without committing)

git status

git diff

3️.Peek at a specific commit

git show <commit-hash>

4️.Peek at a file from another branch

git show main:file.txt

90. Async function in go

Ans: “Golang doesn’t have async/await; instead it uses goroutines to run functions concurrently. When a function is started with the go keyword, it executes independently without blocking the caller. However, we must synchronize using WaitGroups, channels, or context to prevent premature exits and race conditions.”
“Concurrency is not parallelism — Go enables concurrency, and parallelism happens when multiple CPU cores execute goroutines.”
Common Problems When Running Async Code:
Race Conditions

Multiple goroutines accessing shared memory.

✅ Fix → Mutex

  1. Goroutine Leaks

If goroutines never stop → memory usage increases.

✅ Fix → Context / cancellation.

  1. Deadlocks

When goroutines wait forever.
When Should You Use Async in Go?

Best for:

✅ API calls
✅ File processing
✅ Background jobs
✅ Microservices
✅ Parallel computation

91.How to Reduce GC Overhead

1. Reduce Allocations

Reuse objects instead of creating new ones.

Using sync.Pool
2. Avoid Unnecessary Pointers

More pointers → more work for GC.

92.Does GC Prevent Memory Leaks

No — not always.

If something is still referenced (like a stuck goroutine), GC cannot remove it.

Go uses a concurrent tri-color mark-and-sweep garbage collector. It identifies reachable objects from root references, deletes unreachable ones, and runs mostly in the background to minimize pause times. While GC automates memory management, developers must still avoid holding unnecessary references to prevent memory leaks.”
Memory leaks in Go usually happen due to stuck goroutines, unclosed resources, growing maps, or slice retention. Even with garbage collection, objects that remain referenced cannot be freed. We detect leaks using pprof and runtime metrics, and prevent them by closing resources, using context cancellation, and controlling goroutines.”
Best Practices to Prevent Memory Leaks

 Always close resources

Use defer

✔ Control goroutines

Use:

  • Context cancellation
  • Timeouts
  • Worker pools
  • Avoid Global Variables
  • They stay for the app lifetime.
    Limit Cache Size
  • Never allow unbounded growth.
  • Use Buffered Channels Carefully
  • Huge buffers = high memory usage.

93.What is Garbage Collection (GC) in Golang?

Garbage Collection is an automatic memory management process that frees memory occupied by objects no longer in use.

👉 You don’t manually free memory like in C/C++ — Go handles it for you.

Goal:
✅ Prevent memory leaks
✅ Reduce manual memory handling
✅ Improve developer productivity

94.What is gateway

An API Gateway is a centralized entry point that manages client requests and routes them to appropriate microservices. It handles cross-cutting concerns like authentication, rate limiting, caching, and load balancing, improving security and scalability.”
With Gateway Benefits:

✅ Centralized security
✅ Easier monitoring
✅ Better scalability
✅ Cleaner architecture

Popular API Gateways (Interview Bonus)

👉 Mentioning these impresses interviewers:

  • NGINX
  • Kong
  • AWS API Gateway
  • Apigee
  • Traefik

95.Common Ways to Handle Errors

Return the Error
2. Wrap Errors (VERY IMPRESSIVE IN INTERVIEWS)

Provides more context.

if err != nil {

return fmt.Errorf(“failed to open file: %w”, err)}

  1. Custom Errors
When you want business-level error messages.
var ErrUserNotFound = errors.New(“user not found”)

77.When Does Panic Occur?

Runtime Errors (MOST COMMON)

Go automatically triggers panic in situations like:

✅ Index out of range
✅ Nil pointer dereference
✅ Divide by zero
✅ Closing a nil file
✅ Writing to a closed channel

Panic vs Error (EXTREMELY IMPORTANT)

Panic Error
Crashes program Returned and handled
For unexpected situations For expected failures
Rare usage Recommended approach
How to Stop a Panic? 
→ recover()You can catch panic using recover inside a deferred function.

96.How do you stop one microservice from calling another repeatedly?

✅ Rate limiting
✅ Circuit breaker
✅ Retry with backoff
✅ Caching

⭐ Mention tools like:

  • Redis
  • API Gateway

WHERE vs HAVING

👉 WHERE: filters before grouping
👉 HAVING: filters after GROUP BY

1. Primary Key vs Unique Key
Primary Key Unique Key
Only one per table Multiple allowed
Cannot be NULL Can be NULL

 

97. Why is Golang fast?

Reasons:

  • Compiled language
  • Goroutines (lightweight threads)
  • Efficient garbage collector
  • Minimal runtime

98. Docker commands

1.docker –version

2.docker pull nginx

3.docker images
4. docker run -d -p 8080:80 nginx

5.docker ps- list of running containers

6.docker stats- Check Resource Usage

7. docker-compose up -d

99. Fiber vs Gin

Fiber

  • Built on fasthttp (high-performance HTTP engine).
  • Does not use Go’s net/http.
  • Optimized for speed and low latency.

🔥 Result → Better raw performance.
  Fiber can handle more requests per second.

  Lower memory footprint.

  Great for high-throughput microservices.

In real production, database queries and architecture matter more than framework speed.
Choose Fiber if:

✅ You need ultra-high performance
✅ Building lightweight microservices
✅ Want Express.js-like syntax
✅ Expect massive concurrent traffic

 Gin

  • Built directly on net/http.
  • More aligned with standard Go practices.
  • Highly stable for production systems.

🔥 Result → Better reliability + compatibility.

When to Choose Gin

Choose Gin if:

✅ You want production-proven stability
✅ Prefer standard Go behavior
✅ Need strong community support
✅ Building enterprise APIs

100. which command used to install fiber in Golang

go get github.com/gofiber/fiber/v2

 

101. JWT Parameters

Header.Payload.Signature
1. Header

The header contains metadata about the token.

Common parameters:

  • alg → Algorithm used for signing the token
    Example: HS256, RS256
  • typ → Token type (always JWT)
  1. Payload (Claims)

The payload holds the actual data you want to transmit.

Claims are of three types:

✔ Registered Claims (Standard)

These are predefined and recommended:

  • iss (Issuer) → Who created the token
  • sub (Subject) → User identifier
  • aud (Audience) → Who the token is intended for
  • exp (Expiration Time) → When token expires
  • nbf (Not Before) → Token valid after this time
  • iat (Issued At) → When token was generated
  • jti (JWT ID) → Unique token ID
  • Signature
  • Used to verify the token is not tampered with.

102. What is GraphQl

GraphQL exposes a single endpoint, and each field in the schema is backed by a resolver that can independently call a different API. Each resolver independently calls a different backend service, and the GraphQL execution engine orchestrates, parallelizes, and merges the results into one response.

103.How Goroutines Work Internally (G-M-P Model)

Go uses the GMP scheduler:

  • G (Goroutine) → your function
  • M (Machine) → OS thread
  • P (Processor) → scheduler context

👉 Many goroutines run on few OS threads
G – Goroutine

  • Lightweight execution unit
  • Starts with ~2KB stack
  • Created using go func()
  • Contains:
    • stack
    • instruction pointer
    • state (runnable, running, waiting)
      M – Machine (OS Thread)
    • An actual OS thread
    • Executes Go code
    • Can run only one goroutine at a time
    • If an M blocks (e.g., syscall), Go creates or reuses another M

P – Processor (Scheduler Context)

  • The most important part
  • Holds:
    • run queue of goroutines
    • scheduler state
  • Controls how many goroutines can run in parallel

🔑 Number of P = GOMAXPROCS

How GMP Works (Step-by-Step)

1️⃣ Goroutine (G) is created
2️⃣ It is placed in a P’s local run queue
3️⃣ M picks up a P
4️⃣ M executes G using P
5️⃣ When G blocks → M parks it → scheduler picks next G

104. Why use slice instead of array?

  1. Flexibility → size can change dynamically.
  2. Efficiency → slices avoid copying data unnecessarily (share underlying array).
  3. Simplicity → slices are easier to work with (append, copy, slicing).
  4. Idiomatic Go → slices are the standard way to handle collections in Go.
  1. Call by value → function gets a copy (safe, but original unchanged).
  2. Call by reference → function gets address (efficient, can modify original).
  3. Slices > Arrays → because slices are dynamic, flexible, and Go’s idiomatic way.

105. The difference between == and === operators is mainly in type coercion.

: == (Loose Equality)

  • Compares two values after converting them to a common type (type coercion).
  • Returns true if the values are equal after type conversion.

✅ === (Strict Equality)

  • Compares both value and type.
  • Returns true only if both the value and type are exactly the same.

console.log(5 == “5”);        // true (string “5” is converted to number 5)

console.log(true == 1);       // true (true is converted to 1)

console.log(null == undefined); // true (special case)

 

// Using ===

console.log(5 === “5”);       // false (number !== string)

console.log(true === 1);      // false (boolean !== number)

console.log(null === undefined); // false (different types)

106. If one microservice calling many times to another microservice what should we use to stop that in Golang.

: Circuit Breaker (MOST IMPORTANT)

Stops calls automatically when the downstream service is failing or slow.

Why?

  • Prevents cascading failures
  • Gives the downstream service time to recover

Popular Go libraries

  • sony/gobreaker
  • resilience4go
    Rate Limiting
  • Limits how many requests a service can send or receive.
  • Use when
  • One service is flooding another
  • Prevents overload

Timeout + Context (MANDATORY)
Caching (Reduce repeated calls)

If data doesn’t change frequently:

  • Redis
  • In-memory cache

107. When CPU spike

CPU spikes occur when workload suddenly increases due to high traffic, inefficient code, excessive concurrency, garbage collection, or heavy computations. They are diagnosed using system metrics and profiling tools and mitigated through optimization, rate limiting, and autoscaling.

108.What is sharding?

Sharding is a technique used to split data into smaller, independent parts called shards. Each shard stores only a portion of the total data, allowing your application to scale horizontally.

For example, instead of storing all 1 million users in one map or database:

  • Shard 1: User IDs 1–250,000
  • Shard 2: User IDs 250,001–500,000
  • Shard 3: User IDs 500,001–750,000
  • Shard 4: User IDs 750,001–1,000,000

When a request comes in, you determine which shard contains the data.


Why use sharding in Go?

Sharding is commonly used in Go to:

  • Reduce lock contention
  • Improve concurrent performance
  • Scale large in-memory data structures
  • Distribute data across multiple databases or servers

Example 1: Sharding a map

Suppose many goroutines are reading and writing to a map.

Without sharding

type Cache struct {
    mu sync.RWMutex
    data map[string]string
}
Every operation must acquire the same mutex.
100 goroutines
      ↓
 Single RWMutex
      ↓
     Map
This becomes a bottleneck.

With sharding

Create multiple smaller maps, each with its own mutex.

type Shard struct {
    mu   sync.RWMutex
    data map[string]string
}

const NumShards = 16

type ShardedCache struct {
    shards [NumShards]Shard
}
Each key belongs to one shard.
func getShard(key string) int {
    h := fnv.New32a()
    h.Write([]byte(key))
    return int(h.Sum32()) % NumShards
}
Usage:
func (c *ShardedCache) Set(key, value string) {
    shard := &c.shards[getShard(key)]

    shard.mu.Lock()
    shard.data[key] = value
    shard.mu.Unlock()
}
Now:
100 goroutines

 ↓     ↓     ↓     ↓

Shard0 Shard1 Shard2 ... Shard15
 Lock    Lock    Lock       Lock
 Map     Map     Map        Map
  1. Consistent hashing

Used in distributed systems because it minimizes data movement when adding or removing shards.


Advantages

  • Higher concurrency
  • Better scalability
  • Reduced lock contention
  • Better CPU utilization
  • Can distribute load across multiple machines

Disadvantages

  • More complex implementation
  • Data lookup requires shard calculation
  • Rebalancing data when changing the number of shards can be difficult (unless using consistent hashing)
  • Cross-shard queries or transactions are more complicated

When should you use sharding in Go?

Use sharding when:

  • You have a shared map accessed by many goroutines.
  • A single mutex becomes a performance bottleneck.
  • You need to scale data across multiple servers or databases.
  • You’re building high-performance systems like caches, rate limiters, or session stores.

Avoid it if:

  • Your application has low concurrency.
  • The data set is small.
  • The added complexity outweighs the performance benefits.

109.Class in Golang?

Golang does not have classes.

Instead, Go uses:

  • structs → data
  • methods on structs → behavior
  • interfaces → abstraction
  • composition → reuse

110. What is Cherry-Pick in Git?

git cherry-pick is a Git command used to apply a specific commit from one branch into another branch without merging the entire branch.

111.Categories of Data Types in Golang.

Golang data types are mainly divided into four categories:

1️.Basic data types
2️.Composite data types
3️.Reference data types
4️.nterface data type

“Golang data types include basic types like int, float, string, and bool; composite types like array, slice, struct, and map; reference types like pointer and channel; and interface types for abstraction.”

112.Can class call within class in Golang?

Why “class within class” doesn’t exist in Go

  • Go has no class keyword
  • No inheritance like Java
  • Go follows composition over inheritance

1.One struct using another struct (composition)

2.Struct embedding (most Go-idiomatic way)

Equivalent to inheritance-like behavior

3.Using interfaces (recommended for large projects)

113. What is anonymous struct in Golang.

An anonymous struct is a struct declared without a type name and typically used for temporary or inline data structures.
person := struct {

Name string

Age  int

}{Name: “Smita”,

Age:  25,

}

  • fmt.Println(person.Name)
    No type Person struct
  • Struct is declared and initialized directly
  • It exists only in that scope

🔹 Why Use Anonymous Struct?

✔ Temporary data
✔ JSON responses
✔ Testing
✔ One-time use structures
✔ Avoid creating unnecessary types.

114.What is diff between new and init keyword in Golang.

new is a built-in function used to allocate memory.
         Allocates memory for a type

  Returns a pointer to zero value of that type

init() is a special function that runs automatically:

  • Before main()
  • When a package is initialized
      Cannot be called manually
  •   Cannot take arguments
  •   Cannot return values
  •   Can have multiple init() functions
new make
Allocates memory Initializes slice, map, channel
Returns pointer Returns actual type
Works for any type Only slice, map, channel

 

115.What is difference between package and module.

A package is a collection of Go source files in the same directory that are compiled together.
A package is a folder containing Go files that share the same package name.
A module is a collection of related Go packages.

It is defined by a go.mod file.

A module is a versioned collection of Go packages.

This defines:

  • Module name, Go version, Dependencies

116. How to detect race condition happened in code

Use Go Race Detector
       go run -race main.go
Common Signs of Race Condition

Even without race detector:

  • Inconsistent output
  • Unexpected values
  • Program behaves differently each run
  • Random crashes

117.How to compile go code in windows and linux

go build main.go

Compile Windows binary from Linux

GOOS=windows GOARCH=amd64 go build main.go

Compile Linux binary from Windows (PowerShell)

$env:GOOS=”linux”

$env:GOARCH=”amd64″

go build main.go

118.How do you handle API failure?

  • Retry mechanism
  • Proper error messages
  • Logging

119.what is retry mechanism.

A retry mechanism is a technique where a system automatically tries an operation again if it fails.
  Network issues

  Timeout errors

  Server overload What is a Load Balancer in Golang?

👉 A load balancer in Golang is a program/service written in Go that distributes incoming requests across multiple backend servers to improve performance, scalability, and availability.

120. select in Golang.

select is used to handle multiple channel operations concurrently. It executes the case that is ready first.

Advantages:

  • Non-blocking concurrency
  • Timeout handling
  • Efficient goroutine coordination

121.How do you handle high traffic?

  • Load balancing
  • Caching
  • DB indexing
  • Horizontal scaling

122.How do you debug production issues?

  • Logs
  • Monitoring (CloudWatch)
  • Metrics
  • Tracing

123.How do you ensure code quality?

  • Unit testing
  • Code reviews
  • Linting
  • CI pipeline

124.Why Load Balancing is Needed.

  • Prevent server overload
  • Improve response time
  • Ensure high availability
  • Handle high traffic

🔄 How It Works

  1. Client sends request
  2. Load balancer receives it
  3. Chooses a server
  4. Forwards request
  5. Sends response back

Types of Load Balancing
1. Round Robin

  • Requests distributed one by one
  1. Least Connections
  • Sends request to server with least active connections
  1. IP Hash
  • Same user → same server
  1. Weighted Load Balancing
  • More powerful server gets more traffic

125.What is stateless Api.

A stateless API is an API where each request from the client contains all the information needed to process it, and the server does not store any client session data between requests.

Why Stateless APIs are Important

  • Horizontal scaling (add more servers easily)
  • Fault tolerance
  • Better performance
  • Works well with microservices

126.What is routing in Golang.

Routing in Golang means mapping an incoming HTTP request (URL + method) to a specific handler function that processes it and returns a response.

How Routing Works

  1. Client sends request (URL + method)
  2. Router matches path
  3. Calls corresponding handler
  4. Sends response

Types of Routing
Static Routing
Dynamic Routing
Query Parameters

127. what is diff between httphandlefunc and httpmethod

http.HandleFunc is used to register a route in Go’s net/http package, mapping a URL to a handler function. HTTP methods like GET and POST define the type of operation on that route. With HandleFunc, we manually check the method using r.Method, whereas frameworks like Gin or Fiber provide built-in method-based routing.
Ans:-

Concept Meaning
http.HandleFunc Registers a route (URL → handler)- net/http package
HTTP Method Defines the type of request (GET, POST, PUT, DELETE)
 

Problem with http.HandleFunc

  • No built-in method separation
  • You must manually write conditions
  • Not scalable for large APIs

128. What is slide window in DS

Sliding Window is a technique used in Data Structures and Algorithms to process a subset (window) of elements in an array or string efficiently by moving the window step-by-step instead of recalculating everything.

129.Why Use Sliding Window?

  • Reduces time complexity
  • Avoids nested loops

Converts O(n²) → O(n)

Types of Sliding Window

  1. Fixed Size Window

Window size remains constant

👉 Example: max sum of subarray of size k

  1. Variable Size Window

Window expands/shrinks dynamically

👉 Example: longest substring without repeating characters

130.What is a goroutine leak?

When goroutines keep running but are no longer needed → memory leak.

👉 Fix:

  • Use context.WithCancel
  • Proper channel closing
  • Avoid infinite loops

131.How to design high-scale low-latency system?

  • Caching (Redis)
  • Load balancing
  • Horizontal scaling
  • Async processing (Kafka)
  • DB indexing
  • CDN

132.How to reduce latency?

  • Use cache
  • Reduce DB calls
  • Use connection pooling
  • Optimize queries

133.What is context switching?

Switching CPU from one process/thread to another..

134. What is Variable Scope?

Variable scope is the region of a program where a variable is declared and can be used.

135. what is connection pool in Golang

A connection pool in Golang is a collection of reusable connections (typically database or network connections) that are kept open and shared across multiple requests instead of creating a new connection every time.

Creating a new database connection is expensive because it involves network communication, authentication, and resource allocation. A connection pool improves performance by reusing existing connections.

How it works

Suppose your application receives 1,000 requests:

  • Without a connection pool
    • Request 1 → Create connection → Execute query → Close connection
    • Request 2 → Create connection → Execute query → Close connection
    • This is slow and consumes more resources.
  • With a connection pool
    • At startup, Go creates (or lazily opens) a set of connections.
    • Request 1 uses Connection 1 and returns it to the pool.
    • Request 2 uses Connection 2 and returns it.
    • Other requests reuse these connections.

      Connection Pool in Go

      The database/sql package automatically manages a connection pool.

      db, err := sql.Open("postgres", connStr)
      if err != nil {
          log.Fatal(err)
      }
      defer db.Close()
      You don’t need to manually create or manage individual database connections.

      Important Pool Settings

      1. Maximum Open Connections

      db.SetMaxOpenConns(20)
      At most 20 database connections can be open simultaneously.

      2. Maximum Idle Connections

      db.SetMaxIdleConns(5)

      Keeps 5 idle connections ready for reuse.

      3. Maximum Connection Lifetime

      db.SetConnMaxLifetime(time.Hour)
      Recreates a connection after it has been open for 1 hour.

      4. Maximum Idle Time

      db.SetConnMaxIdleTime(10 * time.Minute)
      Closes idle connections after 10 minutes.

       Example

      package main
      
      import (
      	"database/sql"
      	"log"
      	"time"
      
      	_ "github.com/lib/pq"
      )
      
      func main() {
      	db, err := sql.Open("postgres", "host=localhost user=postgres password=123 dbname=test sslmode=disable")
      	if err != nil {
      		log.Fatal(err)
      	}
      	defer db.Close()
      
      	db.SetMaxOpenConns(20)
      	db.SetMaxIdleConns(5)
      	db.SetConnMaxLifetime(1 * time.Hour)
      	db.SetConnMaxIdleTime(10 * time.Minute)
      
      	err = db.Ping()
      	if err != nil {
      		log.Fatal(err)
      	}
      
      	log.Println("Database connected successfully")
      }
      Benefits
      • Faster performance because connections are reused.
      • Reduces the overhead of creating and closing connections.
      • Limits the number of simultaneous database connections.
      • Improves scalability for high-traffic applications.
      • Helps prevent exhausting database resources.
  • 136.Can multiple goroutines acquire the same mutex?

    No. Only one goroutine can hold a sync.Mutex at a time. Others block until it is unlocked.

    137. What happens if you forget to unlock a mutex?

               Other goroutines waiting on that mutex will block indefinitely, which can lead to a deadlock.

       mu.Lock()
        defer mu.Unlock()

138.Mutex vs RWMutex

Mutex RWMutex
One goroutine at a time (read or write) Multiple readers allowed simultaneously
Simpler Better for read-heavy workloads
Lock() / Unlock() RLock() / RUnlock() for reads, Lock() / Unlock() for writes

139.what is deadlock

A deadlock is a situation where two or more goroutines are permanently blocked, waiting for each other (or waiting for an event that will never happen). As a result, the program cannot make further progress.

ex. sending to a channel with no receiver

package main

func main() {

ch := make(chan int) ch <- 10

}

Why?

  • An unbuffered channel requires a receiver.
  • No goroutine is receiving.
  • The send operation blocks forever.

140. what is escape analysis in Golang

Escape analysis is a compiler optimization in Go that determines whether a variable should be allocated on the stack or the heap.

  • Stack allocation → Faster, automatically freed when the function returns.
  • Heap allocation → Slower, managed later by the garbage collector.

The Go compiler performs escape analysis at compile time.


Stack vs Heap

Stack

  •   Fast allocation and deallocation.
  •  Memory is automatically released when the function returns.
  • Used for local variables that don’t outlive the function.
  • Heap
  • Slower allocation.
  • Memory is managed by the garbage collector (GC).
  • Used when data needs to live beyond the function call.

Why is Escape Analysis Important?

  • Reduces heap allocations.
  • Lowers garbage collection overhead.
  • Improves application performance.
  • Helps Go automatically manage memory efficiently without requiring manual allocation.

141.what is leak memeory?

A memory leak occurs when a program continues to hold memory that it no longer needs, so that memory cannot be reclaimed. Over time, memory usage grows unnecessarily, which can lead to poor performance or even crashes.

In Go, memory leaks are different from languages like C/C++ because Go has garbage collection (GC).

  • C/C++: A memory leak often means allocated memory was never freed.
  • Go: A memory leak usually means your program still has references to objects it no longer needs, so the garbage collector cannot free them.
  • Example

       Global Slice Keeps Growing
   Holding References

How to Prevent Memory Leaks

  • Remove references to objects that are no longer needed.
  • Close files, database rows, and network connections.
  • Cancel goroutines using context.Context or proper signaling.
  • Avoid unbounded growth of slices, maps, or caches.
  • Close channels when appropriate.
  • Monitor memory usage using profiling tools such as pprof.

Detecting Memory Leaks

Use Go’s built-in profiling tools:

Memory Profile

go tool pprof http://localhost:6060/debug/pprof/heap

Goroutine Profile

go tool pprof http://localhost:6060/debug/pprof/goroutine
You can also monitor memory with:
import "runtime"
var m runtime.MemStats
runtime.ReadMemStats(&m)
fmt.Println(m.Alloc)

142.What is the difference between a memory leak and a goroutine leak?

Memory Leak Goroutine Leak
Unused memory remains referenced and cannot be collected Goroutines remain blocked or running forever
Increases heap usage Increases goroutine count and resource usage
Affects GC and memory Affects memory, scheduling, and CPU resources

143.I have 1000 request what services used in Golang or Aws how can I handle?

To handle 1,000 concurrent requests, I would deploy multiple instances of my Go application behind an AWS Application Load Balancer. Since Go handles each HTTP request in its own goroutine, it can efficiently process many concurrent requests. I would configure a database connection pool to avoid opening a new connection per request and use Redis to cache frequently accessed data, reducing database load. For CPU-intensive or long-running tasks, I’d use a worker pool in Go or offload the work to Amazon SQS with background workers. On AWS, I’d enable Auto Scaling so additional instances are created automatically when traffic increases. Files would be stored in Amazon S3, and the database would be hosted on Amazon RDS or Aurora with read replicas if needed. This architecture is scalable, resilient, and suitable for production workloads.

Goroutines

Each HTTP request is handled in its own goroutine.

func handler(w http.ResponseWriter, r *http.Request) {
    // Each request runs concurrently
}

Go can efficiently handle thousands of concurrent goroutines because they are lightweight.


Worker Pool

If processing is CPU-intensive or involves background work, use a worker pool to limit concurrency.

jobs := make(chan Job, 100)

for i := 0; i < 10; i++ {
    go worker(jobs)
}

This prevents creating an unbounded number of goroutines.


Database Connection Pool

Reuse database connections instead of opening one per request.

db.SetMaxOpenConns(100)
db.SetMaxIdleConns(20)

Context with Timeouts

Avoid requests hanging forever.

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

Redis Cache

Cache frequently accessed data to reduce database load.

Example:

  • Product list
  • User profile
  • Dashboard data

2. AWS Services

Application Load Balancer (ALB)

Distributes incoming requests across multiple Go application instances.

1000 Requests
      |
      v
     ALB
   /  |   \
App1 App2 App3

Auto Scaling Group

Automatically adds or removes EC2 instances based on metrics such as CPU utilization or request count.

For example:

  • 2 instances normally
  • Scale to 10 instances during high traffic

Amazon ECS or Kubernetes (EKS)

Instead of running directly on EC2, deploy your Go application as containers.

Benefits:

  • Easier deployments
  • Health checks
  • Automatic scaling
  • Rolling updates

Amazon RDS / Aurora

Use a managed relational database.

Configure:

  • Read replicas for read-heavy workloads
  • Connection pooling
  • Backups and high availability

Amazon ElastiCache (Redis)

Cache frequently requested data.

Benefits:

  • Faster response times
  • Reduced database load

Amazon S3

Store uploaded files, images, PDFs, logs, etc., rather than keeping them on EC2 instances.


Amazon SQS

If a request triggers long-running work (email sending, report generation, image processing), enqueue it instead of processing synchronously.

144. what is ECS

Amazon ECS (Elastic Container Service) is a fully managed container orchestration service provided by AWS. It allows you to deploy, run, scale, and manage Docker containers without having to manage the orchestration software yourself.

Think of ECS as a service that runs your containerized applications reliably in production.


Why do we use ECS?

Suppose you have a Go application.

Without ECS:

  • Create EC2 instance
  • Install Docker
  • Run Docker container manually
  • Restart container if it crashes
  • Scale manually

With ECS:

  • Deploy the Docker image.
  • ECS starts the container.
  • Restarts it if it crashes.
  • Scales it automatically.
  • Integrates with a Load Balancer.

145.what is GMP?

GMP is the scheduling model used by the Go runtime to efficiently execute goroutines on operating system (OS) threads.

GMP stands for:

  • G = Goroutine
  • M = Machine (OS Thread)
  • P = Processor (Logical Processor)

The Go scheduler uses these three components to run thousands or even millions of goroutines efficiently.


Why is GMP needed?

The operating system schedules threads, not goroutines.

Go introduces its own scheduler to map many goroutines onto a smaller number of OS threads.

Advantages of GMP

  • Efficient scheduling of millions of goroutines.
  • Low memory overhead compared to OS threads.
  • Good CPU utilization through work stealing.
  • Handles blocking operations without stalling all goroutines.
  • Supports scalable concurrent applications.

146.GMP Is increase thread or decrease ?

Neither. GMP itself does not simply increase or decrease threads. Instead, it efficiently manages a small number of OS threads (M) to run a large number of goroutines (G).

Does GMP increase threads?

Yes, but only when necessary.

For example:

  • If an OS thread blocks on a system call (e.g., file I/O or a network operation), the Go runtime may create another thread so that other goroutines can continue running.
  • When the blocked thread becomes available again, the runtime can reuse it.

Does GMP decrease threads?

Yes. The runtime can reuse existing threads and avoid creating unnecessary ones. Idle threads may eventually be cleaned up.

Interview Answer

“GMP doesn’t simply increase or decrease threads. Its purpose is to efficiently schedule many goroutines onto a smaller number of OS threads. Go creates additional OS threads only when needed, such as when a thread blocks on a system call, and it reuses threads whenever possible. This allows Go applications to handle thousands of concurrent goroutines without creating thousands of OS threads.”

Key point to remember:

  • Goroutines can be in the millions.
  • OS threads are kept relatively few and are managed by the Go runtime.
  • GMP’s goal is to minimize thread creation while maximizing CPU utilization.

147.what is dependency injection in Golang?

Dependency Injection (DI) is a design pattern where an object receives its dependencies from outside instead of creating them itself.

Don’t create dependencies inside a struct or function; inject them from outside.

This makes your code loosely coupled, easier to test, and easier to maintain.

148.what is url shortner ?

A URL Shortener is a service that converts a long URL into a short, unique URL.

Example

Original URL:

https://www.example.com/products/electronics/mobile/apple/iphone-16-pro-max?color=black&storage=256GB
Short URL:
https://short.ly/aB12Cd
When a user visits the short URL, they are redirected to the original long URL.

How it Works

User
  |
  | 1. Submit Long URL
  v
+----------------+
| URL Shortener  |
+----------------+
        |
        | Generate Unique ID
        v
+----------------+
| Database       |
| aB12Cd -> Long URL |
+----------------+
        |
        | Return Short URL
        v
https://short.ly/aB12Cd
When someone opens the short URL:
User
  |
  | GET /aB12Cd
  v
URL Shortener
  |
  | Lookup in Database
  v
Long URL
  |
  | HTTP 301/302 Redirect
  v
Original Website

How to Generate the Short Code

Common approaches:

1. Base62 Encoding (Most Common)

Characters:

0-9

A-Z
a-z

2.Random String
3.
Hashing
Use algorithms like MD5 or SHA-256 and take a portion of the hash.

149.whay microservices used in Golang main purpose ?

The main purpose of microservices is to break a large application into smaller, independent services, where each service is responsible for a single business capability.

Golang is widely used for microservices because it is fast, lightweight, supports concurrency well, and uses less memory.

2. Scalability

Suppose:

  • User Service receives 100 requests/minute
  • Product Service receives 500 requests/minute
  • Order Service receives 5,000 requests/minute

With microservices, you can scale only the Order Service.

User Service      x1
Product Service   x2
Order Service     x10

This saves infrastructure costs.


3. Fault Isolation

If the Notification Service crashes:

Notification ❌
The User, Product, and Order services can continue working.

In a monolithic application, one failure might affect the whole application.


4. Technology Flexibility

Different services can use different technologies if needed.

Example:

  • User Service → Golang
  • Recommendation Service → Python
  • Analytics → Java

5. Faster Development

Different teams can work on different services simultaneously.

Team A → User Service
Team B → Order Service
Team C → Payment Service

Why Golang for Microservices?

Golang is a good fit because it offers:

  • Fast execution
  • Lightweight goroutines for handling many concurrent requests
  • Low memory usage
  • Fast startup time
  • Simple deployment (single binary)
  • Strong standard library for HTTP, JSON, and networking

Communication Between Microservices

Services communicate using:

  • REST APIs
  • gRPC
  • Message queues (Kafka, RabbitMQ, Amazon SQS)

150. If i stored password in properties file and i want to print that how i print that ?

func main() {

err := godotenv.Load(“.env”)

if err != nil {

log.Fatal(“Error loading .env file”)

}

password := os.Getenv(“DB_PASSWORD”) // Only for debugging – not recommended in production

fmt.Println(“Password:”, password)

}

Technically, I can read it from the configuration and print it. However, in production applications I avoid logging or printing passwords because they are sensitive credentials. Instead, I verify that the value is loaded by masking it or by checking its presence, and I prefer storing secrets in a secure secret manager or environment variables rather than directly in a properties file.

151.which channel is synchronous in Golang?

Unbuffered channels are synchronous because the sender and receiver must rendezvous at the same time. A send operation blocks until another goroutine receives the value, and a receive blocks until another goroutine sends one.

Follow-up: Which channel is asynchronous?

Buffered channels are asynchronous because they allow sends to proceed without an immediate receiver, as long as there is space available in the buffer. Once the buffer is full, send operations block until a receiver consumes a value.

152.what is synchronous?

Synchronous means one operation waits for another operation to complete before continuing.

Synchronous means one operation waits for another operation to complete before proceeding. In Go, an unbuffered channel is synchronous because the sender blocks until a receiver is ready, and the receiver blocks until a sender provides a value. This synchronization ensures both goroutines meet at the communication point.

 

Leave a Reply

Your email address will not be published. Required fields are marked *