Go, End to End
Functions
Functions in Go can return more than one value, which is the language's actual answer to error handling (covered in depth in its own chapter), and they're first-class values: you can hold a function in a variable, pass it as an argument, and return one from another function.
Multiple return values
This is why almost every standard library function that can fail returns (value, error) as its last two results. There's no exception mechanism forcing you to guess where failures can surface, the function signature tells you directly.
Named returns and naked return
Return values can be named in the function signature, which pre-declares them as local variables inside the function body. A bare return (a "naked return") then returns whatever those named variables currently hold.
Naked returns are handy in short functions but get confusing fast in longer ones, since the reader has to scroll back up to remember what x and y even are. Most style guides (including the standard library's own conventions) reserve naked returns for very short functions and use explicit return x, y everywhere else.
Variadic functions
A parameter of the form ...T accepts any number of T arguments, which arrive inside the function as a []T slice. fmt.Println itself is variadic, that's how it accepts any number of arguments.
Closures
A function literal defined inside another function captures the surrounding variables by reference, not by value. Each call to the outer function that returns a closure gets its own independent captured state.
The loop variable capture gotcha
Before Go 1.22, a for loop's variable was a single variable reused across every iteration, not a fresh one per iteration. If you captured it in a closure or a goroutine without being careful, every closure ended up sharing the same variable and seeing its final value, not the value at the time it was created.
Go 1.22 changed the language so that each loop iteration gets its own fresh copy of the loop variable, which is why this exact example behaves differently depending on which Go version compiled it. It's one of the few genuine semantic changes the language has made, specifically because this gotcha caused so many real bugs. Older code and tutorials written before 1.22 often work around it manually by shadowing the variable inside the loop body (i := i), which is worth recognizing even though you rarely need to write it yourself on modern Go.
Try it yourself: run the example above. Whatever result you get tells you which Go version the playground is running.