How to Pass a Go Interview: Top Questions and Answers

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

How to Pass a Go Interview: Top Questions with Code Examples



An interview for a Go developer position is not only a test of syntax but also a deep understanding of the concurrency model, memory management, and the idiomatic style of the language. In this article, we have broken down the top 10 questions most frequently asked in Golang interviews, with detailed answers and code examples. The material is suitable for both Junior and Middle levels.



1. Goroutines vs OS Threads: What is the Difference?

This is a basic question that tests understanding of the Go execution model. The answer should be clear:

  • Stack size: A goroutine starts with a ~2 KB stack that grows dynamically. An OS thread has a fixed stack (1-8 MB).
  • Context switching: Goroutines are switched in user space (Go scheduler). Threads are switched via a system call (more expensive).
  • Creation cost: A goroutine costs ~4 KB of memory, a thread costs ~1 MB. You can run thousands of goroutines.
// Example: 10000 goroutinesfunc main() {    for i := 0; i < 10000; i++ {        go func(n int) {            fmt.Println("Goroutine", n)        }(i)    }    time.Sleep(time.Second)}


2. Channels: Buffered and Unbuffered

A question to test understanding of synchronization. Explain the difference with an example:

  • Unbuffered channel: Send blocks until receive. Guarantees synchrony.
  • Buffered channel: Send does not block until the buffer is full. Allows asynchronous transmission.
// Unbuffered channelch := make(chan int)go func() { ch <- 42 }()val := <-ch // Blocks until a value arrives

// Buffered channelbufCh := make(chan int, 2)bufCh <- 1 // Does not blockbufCh <- 2 // Does not block// bufCh <- 3 // Blocks - buffer is full


3. Select and Handling Multiple Channels

The select statement allows waiting on multiple channel operations. Questions often involve default and timeouts:

func main() {    ch1 := make(chan string)    ch2 := make(chan string)

go func() { time.Sleep(2 * time.Second); ch1 <- "from ch1" }() go func() { time.Sleep(1 * time.Second); ch2 <- "from ch2" }()

select { case msg := <-ch1: fmt.Println(msg) case msg := <-ch2: fmt.Println(msg) case <-time.After(3 * time.Second): fmt.Println("Timeout") }}


4. Interfaces: Empty Interface and Type Assertion

Tests understanding of interface{} (any) and safe type casting:

func describe(i interface{}) {    switch v := i.(type) {    case int:        fmt.Printf("Integer: %d", v)    case string:        fmt.Printf("String: %s", v)    default:        fmt.Printf("Unknown type: %T", v)    }}

func main() { describe(42) describe("hello") describe(3.14)}


5. Memory Management: Stack and Heap, Escape Analysis

A question to test understanding of how Go decides where to place variables. The key point is escape analysis:

  • If the compiler sees that a variable may be used after the function returns, it "escapes" to the heap.
  • Using pointers, interfaces, and closures often causes heap allocation.
// Variable x "escapes" to the heapfunc createPointer() *int {    x := 42    return &x // x cannot be on the stack}


6. Defer: Execution Order and Peculiarities

Defer executes on a LIFO (Last In, First Out) basis. Arguments are evaluated at the time of declaration, not execution:

func main() {    x := 10    defe                

Blogs

Book Recommendations