Go MCQs multiple-choice questions with answers & explanations
All 20 Go quiz questions on one page. Pick an answer in your head, then open Show answer to check it and read why. Want a score and a timer? Take them as a quiz instead.
Official reference: Effective Go
- 1.mid
What does this print?
a := []int{1, 2, 3, 4} b := a[:2] b = append(b, 99) fmt.Println(a)- A
[1 2 3 4] - B
[1 2 99 4] - C
[1 2 99] - D
[1 2 3 4 99]
Show answer
Answer: B (
[1 2 99 4])bhas length 2 but capacity 4, because it sharesa's backing array.appendfits within that capacity, so it writes99into index 2 of the shared array andasees it. Slicing witha[:2:2]would cap the capacity and forceappendto copy. - A
- 2.easy
What does this print?
s := []int{10, 20, 30, 40, 50} t := s[1:3] fmt.Println(len(t), cap(t))- A
2 2 - B
2 4 - C
3 5 - D
2 5
Show answer
Answer: B (
2 4)The length is
3 - 1 = 2. The capacity runs from the start of the slice to the end of the backing array, so it is5 - 1 = 4. That hidden capacity is why appending totwould overwrites[3]. - A
- 3.mid
What does this print?
func add(s []int) { s[0] = 9 s = append(s, 4) } func main() { s := []int{1, 2, 3} add(s) fmt.Println(s) }- A
[1 2 3] - B
[9 2 3] - C
[9 2 3 4] - D
[1 2 3 4]
Show answer
Answer: B (
[9 2 3])The function receives a copy of the slice header that points at the same array, so
s[0] = 9is visible to the caller. The literal has capacity 3, soappendallocates a new array and only the local header sees4. The caller's length is still 3. Return the slice when a function appends. - A
- 4.easy
What does this print?
for i := 0; i < 3; i++ { defer fmt.Print(i) }- A
012 - B
210 - C
333 - D
222
Show answer
Answer: B (
210)The arguments of a deferred call are evaluated when the
deferstatement runs, so each call captures the currenti. Deferred calls run in last-in, first-out order when the function returns, giving210. - A
- 5.easy
What does this print?
x := 1 defer fmt.Println("deferred:", x) x = 2 fmt.Println("now:", x)- A
now: 2thendeferred: 1 - B
now: 2thendeferred: 2 - C
deferred: 1thennow: 2 - D
deferred: 2thennow: 2
Show answer
Answer: A (
now: 2thendeferred: 1)deferevaluatesximmediately (it is 1) and delays only the call, which runs afternow: 2when the function returns. To see the latest value, defer a closure:defer func() { fmt.Println(x) }(). - A
- 6.mid
What does
fmt.Println(f())print?func f() (n int) { defer func() { n *= 2 }() return 3 }- A
3 - B
6 - C
0 - DIt does not compile
Show answer
Answer: B (
6)return 3first assigns 3 to the named resultn, then deferred functions run, and only then does the function return. The closure doublesn, so the caller receives 6. This is how deferred code annotates a returned error. - A
- 7.hard
What happens when this program runs?
func handle() { if r := recover(); r != nil { fmt.Println("recovered:", r) } } func main() { defer func() { handle() }() panic("boom") }- AIt prints
recovered: boomand exits normally - BIt crashes with
panic: boom - CIt prints
recovered: <nil> - DIt does not compile
Show answer
Answer: B (It crashes with
panic: boom)recoverstops a panic only when it is called directly by a deferred function. Here the deferred function is the closure andrecoverruns one level deeper insidehandle, so it returnsniland the panic continues. Writingdefer handle()would recover. - AIt prints
- 8.hard
What does this print?
type MyErr struct{} func (*MyErr) Error() string { return "boom" } func find() error { var e *MyErr return e } func main() { fmt.Println(find() == nil) }- A
true - B
false - CIt panics with a nil pointer dereference
- DIt does not compile
Show answer
Answer: B (
false)An interface is nil only when both its dynamic type and value are nil. Returning a nil
*MyErraserrorstores the type*MyErr, so the interface is not nil. Return the literalnilon success. - A
- 9.mid
What happens when you build this code?
type Saver interface{ Save() } type Doc struct{} func (d *Doc) Save() {} func main() { var s Saver = Doc{} s.Save() }- AIt compiles and runs
- BCompile error:
Docdoes not implementSaver(method has pointer receiver) - CIt compiles but panics at run time
- DCompile error:
Saveis declared but not used
Show answer
Answer: B (Compile error:
Docdoes not implementSaver(method has pointer receiver))The method set of
Doccontains only value-receiver methods, whileSavehas a pointer receiver, so only*DocsatisfiesSaver. Usevar s Saver = &Doc{}. Callingd.Save()on an addressable variable works, but that shortcut does not apply to interface satisfaction. - 10.mid
What does this print?
ch := make(chan int, 2) ch <- 1 ch <- 2 close(ch) for i := 0; i < 3; i++ { v, ok := <-ch fmt.Println(v, ok) }- A
1 true,2 true,0 false - B
1 true,2 true, then a panic - C
0 falsethree times - D
1 true,2 true, then a deadlock
Show answer
Answer: A (
1 true,2 true,0 false)Closing does not discard buffered values: receivers drain them first with
ok == true. After that, receives return the zero value andok == falseimmediately, without blocking or panicking. Only sending on a closed channel panics. - A
- 11.easy
What happens when this program runs?
func main() { ch := make(chan int) ch <- 1 fmt.Println(<-ch) }- AIt prints
1 - BIt prints
0 - C
fatal error: all goroutines are asleep - deadlock! - DIt blocks forever with no output
Show answer
Answer: C (
fatal error: all goroutines are asleep - deadlock!)A send on an unbuffered channel waits for a receiver, and the only receive is on the next line of the same goroutine. No other goroutine exists, so the runtime detects that nothing can make progress and aborts. A buffer of 1, or sending from another goroutine, fixes it.
- AIt prints
- 12.easy
What happens when this runs?
ch := make(chan int, 1) close(ch) ch <- 1 fmt.Println("sent")- AIt prints
sent - BIt panics:
send on closed channel - CThe send is silently dropped and
sentis printed - DIt deadlocks
Show answer
Answer: B (It panics:
send on closed channel)Sending on a closed channel always panics, even when the buffer has room. That is why only the sender, which knows when it has finished, should close a channel.
- AIt prints
- 13.easy
What does this print?
ch := make(chan int) select { case v := <-ch: fmt.Println("got", v) default: fmt.Println("empty") }- A
got 0 - B
empty - CIt deadlocks
- DIt prints nothing
Show answer
Answer: B (
empty)No goroutine is sending, so the receive case is not ready. A
selectwith adefaultcase runsdefaultimmediately instead of blocking. Withoutdefault, this would deadlock. - A
- 14.easy
What happens when this runs?
var m map[string]int fmt.Println(m["a"]) m["a"] = 1- APrints
0, then panics:assignment to entry in nil map - BPanics on the first line that reads
m - CPrints
0and stores the value - DCompile error:
mis not initialised
Show answer
Answer: A (Prints
0, then panics:assignment to entry in nil map)Reading from a nil map is allowed and returns the zero value, but writing panics because there is no hash table to write into. Initialise with
make(map[string]int)or a literal. - APrints
- 15.mid
What happens when you build this?
type Counter struct{ N int } m := map[string]Counter{"a": {}} m["a"].N++- AIt compiles and
m["a"].Nbecomes 1 - BIt compiles but the increment is lost
- CCompile error: cannot assign to struct field
m["a"].Nin map - DIt panics at run time
Show answer
Answer: C (Compile error: cannot assign to struct field
m["a"].Nin map)Map elements are not addressable, because the map may move them when it grows, so you cannot assign to a field of a struct stored by value. Read the value, change it and store it back, or use
map[string]*Counter. - AIt compiles and
- 16.mid
The module's
go.moddeclaresgo 1.23. What does this print?var fs []func() for i := range 3 { fs = append(fs, func() { fmt.Print(i) }) } for _, f := range fs { f() }- A
012 - B
333 - C
222 - DCompile error: cannot range over
3
Show answer
Answer: A (
012)Since Go 1.22, each loop iteration has its own
i, so every closure captures a different variable. Go 1.22 also allows ranging over an integer. In a module whosegoline is older than 1.22, the closures would share one variable and print333. - A
- 17.easy
What does this print?
s := "héllo" fmt.Println(len(s), utf8.RuneCountInString(s))- A
5 5 - B
6 5 - C
5 6 - D
6 6
Show answer
Answer: B (
6 5)lencounts bytes. In UTF-8,é(U+00E9) takes two bytes, so the string is 6 bytes long but contains 5 runes. Useutf8.RuneCountInStringorrangeto work with code points. - A
- 18.mid
What does this print?
var ErrNotFound = errors.New("not found") e1 := fmt.Errorf("get user: %w", ErrNotFound) e2 := fmt.Errorf("get user: %v", ErrNotFound) fmt.Println(errors.Is(e1, ErrNotFound), errors.Is(e2, ErrNotFound))- A
true true - B
true false - C
false false - D
false true
Show answer
Answer: B (
true false)Both errors have the same message, but only
%wmakes the new error unwrap toErrNotFound.%vjust formats the text, soerrors.Iscannot find the sentinel ine2. - A
- 19.mid
What does this print?
ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond) defer cancel() select { case <-time.After(time.Second): fmt.Println("finished") case <-ctx.Done(): fmt.Println(ctx.Err()) }- A
finished - B
context canceled - C
context deadline exceeded - D
<nil>
Show answer
Answer: C (
context deadline exceeded)The 50 ms deadline passes before the one-second timer, so
ctx.Done()closes first andctx.Err()returnscontext.DeadlineExceeded.context canceledwould appear only ifcancel()ran before the deadline. - A
- 20.hard
What happens when this program runs with
go run?func worker(wg sync.WaitGroup) { defer wg.Done() fmt.Println("work") } func main() { var wg sync.WaitGroup wg.Add(1) go worker(wg) wg.Wait() fmt.Println("done") }- AIt prints
workthendone - BIt prints
work, then fails withall goroutines are asleep - deadlock! - CIt panics:
sync: negative WaitGroup counter - DIt prints
donethenwork
Show answer
Answer: B (It prints
work, then fails withall goroutines are asleep - deadlock!)workerreceives a copy of the WaitGroup, soDonedecrements the copy and the original counter stays at 1. Once the worker exits,mainis blocked inWaitwith nothing left to wake it, and the runtime reports a deadlock. Pass*sync.WaitGroup;go vetflags the copy. - AIt prints
No questions match these filters. Try a different subtopic or clear the filters.