How to Pass a Go Interview: Top Questions from A to Z
A Go developer interview is not just a syntax check. Employers look for candidates who understand the language's philosophy: simplicity, concurrency, and efficient memory management. In this article, we'll break down the key questions you'll definitely be asked — from the basics to advanced topics with code examples. Prepare using our checklist, and you'll feel confident.
1. Go Basics: Data Types, Structures, and Memory Management
Let's start with the fundamentals. You can't get anywhere without them. Interviewers love to ask questions about types and their behavior.
What built-in data types exist in Go?
- Basic:
int,float64,string,bool. - Aggregate:
array,struct. - Reference:
slice,map,channel,pointer,function.
What is the difference between an array and a slice?
An array has a fixed length set at compile time. A slice is a dynamic structure that references an underlying array.
// Arrayvar arr [3]int = [3]int{1, 2, 3}arr[0] = 10 // Ok
// Sliceslc := []int{1, 2, 3}slc = append(slc, 4) // Length can growStumper question: What happens to memory during append if the slice's capacity is exceeded? (Answer: Go allocates a new array twice as large and copies the data).
How is a map structured in Go?
A map is a hash table. The iteration order is not guaranteed. Reading a non-existent key returns the zero value (e.g., 0 for int).
m := make(map[string]int)m["key"] = 42value, ok := m["key"] // ok == true if the key exists2. Concurrency: Goroutines, Channels, and Mutexes
This is the most important topic for Go. You won't pass the interview without it.
What is a goroutine and how is it different from an OS thread?
A goroutine is a lightweight thread managed by the Go runtime. A goroutine's stack starts at 2-4 KB (compared to 1 MB for an OS thread). Thousands of goroutines run on a few OS threads (M:N model).
How do channels work? Give an example of the worker pool pattern.
func worker(id int, jobs <-chan int, results chan<- int) { for j := range jobs { results <- j * 2 }}
func main() { jobs := make(chan int, 100) results := make(chan int, 100)
// Start 3 workers for w := 1; w <= 3; w++ { go worker(w, jobs, results) }
// Send jobs for j := 1; j <= 5; j++ { jobs <- j } close(jobs)
// Collect results for r := 1; r <= 5; r++ { <-results }}What is the difference between a buffered and an unbuffered channel?
- Unbuffered: The sender blocks until the receiver accepts the message. Synchronous communication.
- Buffered: The sender blocks only when the buffer is full. Asynchronous communication.
How to avoid a deadlock?
Use select with a timeout or default:
select {case msg := <-ch: fmt.Println(msg)case <-time.After(1 * time.Second): fmt.Println("timeout")}3. Interfaces, Generics, and Error Handling
Go is not a pure OOP language, but interfaces play a key role here.
How does duck typing work in Go?
A type implicitly implements an interface if it has all the required methods. This allows for writing flexible code.
type Stringer interface { String() string}
type User struct { Name string}
func (u User) Str