Functions
Functions in Go — multiple and named returns, variadic parameters, first-class function values, and recursion.
7 questions
JuniorTheoryVery commonHow do multiple and named return values work in Go?
How do multiple and named return values work in Go?
A Go function can return several values at once, idiomatically a (T, error) pair returned as return val, err. You can also name the results: named results are pre-declared variables that start at their zero value and stay in scope for the whole body, enabling a naked return that sends back their current values. In an assignment the caller binds every result, discarding unwanted ones with _.
Common mistakes
- ✗Thinking a naked
returnignores the named results instead of sending their current values - ✗Leaving a result out of an assignment:
v := f()for anfwith two results does not compile, so each result needs a variable or_.
Follow-up questions
- →When does a naked
returnhurt readability despite being legal? - →How does a deferred closure interact with a named return value?
JuniorTheoryCommonWhat does the program print?
What does the program print?
11
Open full question →Common mistakes
- ✗Expecting
14:*binds tighter than+, so1 + x*2is1 + (x*2), not(1 + x)*2;f(2)is5andf(5)is11. - ✗Expecting
5or5 11: the inner call's result5is passed tofagain, andfmt.Printlnprints only the value of its argument,f(5).
Follow-up questions
- →What would
fmt.Println(f(2), f(f(2)))print? - →How would you change
fso that it computes(1 + x) * 2?
JuniorTheoryCommonWhat does the program print?
What does the program print?
5 6
Open full question →Common mistakes
- ✗Expecting
6 6:r := op(2, 3)calls the function at once and stores the number 5, not the function. - ✗Expecting
5 5or a compile error: a function is a value, so afunc(int, int) intvariable takes another literal of that type.
Follow-up questions
- →How does an anonymous function become a closure over surrounding variables?
- →What is the zero value of a function-typed variable, and what happens if you call it?
JuniorTheoryCommonWhat does the program print?
What does the program print?
2 1
Open full question →Common mistakes
- ✗Expecting
2 2:nis a copy ofx, son++changes only the copy;increturns2andxstays1. - ✗Expecting
1 1or a compile error: a parameter is an ordinary variable of the function, son++is allowed and changesn, whichincthen returns.
Follow-up questions
- →How would you change
mainso thatxitself becomes2? - →What would the program print if
incnamed its parameterxinstead ofn?
JuniorTheoryCommonWhat is a variadic parameter in Go and how is it passed?
What is a variadic parameter in Go and how is it passed?
Writing ...T on the last parameter makes a function variadic: it collects any number of trailing arguments into a []T slice, so inside the body the parameter is an ordinary slice you can range over. You call it with separate args like f(a, b, c), or spread an existing slice with f(s...). Standard functions such as append and fmt.Println are variadic this way.
Common mistakes
- ✗Forgetting the variadic parameter must be the last one in the signature
- ✗Passing a slice directly instead of spreading it with the
s...form - ✗Assuming the collected arguments are an array rather than a
[]Tslice
Follow-up questions
- →What does passing zero arguments to a variadic parameter give you inside the body?
- →Why can a variadic call sometimes allocate a backing array on the heap?
JuniorTheoryOccasionalWhat does the program print?
What does the program print?
321123
Open full question →Common mistakes
- ✗Expecting
321: the line after the recursive call still runs, once that call returns, so eachcountprints itsntwice. - ✗Expecting
123321or321321: the deepest call finishes first, so the second prints come back in reverse order: 1, 2, 3.
Follow-up questions
- →What error or panic do you get when a Go recursion exhausts the stack?
- →How does the goroutine stack growing on demand differ from a fixed C stack?
MiddleTheoryOccasionalHow can a deferred function modify a named return value?
How can a deferred function modify a named return value?
Named results are real variables that stay in scope until the function actually returns, even after a return statement has set them. A deferred closure — itself a first-class function value — runs in that window, so it can read and reassign them: defer func(){ err = wrap(err) }() overwrites what the caller receives. This is impossible with unnamed returns, since no variable is left for the deferred call to touch.
Common mistakes
- ✗Thinking the defer gets a copy of the result rather than the live variable
- ✗Expecting the same trick to work with unnamed returns, where no variable exists
- ✗Believing the defer runs before
returnsets the result, not after
Follow-up questions
- →In what order do multiple deferred edits to the same named result apply?
- →Why is this pattern common for wrapping or annotating an error before it leaves a function?