I'm fairly sure that almost every statically typed language has function definitions like that. C, C++, Java, Go, Rust and so on all have that style of function declaration.
Named returns are a Go thing mainly because of defer.
As one would expect. The deferred code runs after the normal code in the function has ended, and before the calling code has resumed. Named return values are in scope and can be read and modified.
I'm thinking of it in the way that the interpreter works in JavaScript with tasks. If you setTimeout(A, 0), inside B, then after B returns, A is called, but any other tasks previously inserted into the queue are called first.
So I think that means I was asking about execution in the same context (as in memory context), unless you mean stack frame by context, in which case, I think i understand that because the caller returns the value of the deferred, they are in the same stack frame, and nothing else could insert in that frame between them. I'm not sure you know what i mean, but do i have it about right?
I don't really understand this, but i think I'm getting somewhere.
It's much simpler than that. It's just a way of defining cleanup functions without having a language-level concept of destructors. Here's an example: https://gobyexample.com/defer.
This simple example should explain everything:
package main
import "fmt"
func function1() {
defer fmt.Println("function1: defer a")
fmt.Println("function1: inside")
defer fmt.Println("function1: defer b")
}
func main() {
fmt.Println("main: before function1")
function1()
fmt.Println("main: after function1")
}
Here is the output:
main: before function1
function1: inside
function1: defer b
function1: defer a
main: after function1
All defers run in LIFO order at the point when a function returns before the function returns execution back to the caller.
Ok now I got they are in scope. About defer, could you think of it like defer makes a function into a function with multiple entry and exit points, possible to be stopped and resumed, like a coroutine?
Ehm, not sure I understood, but I'd say no. Defer is just code that is executed in reverse order upon return from a fuction. It has nothing to do with coroutines. It's a cleaner way to write the usual C syntax of "goto cleanup_x" code.
Go coroutines (goroutines) are functions invoked with the "go" keyword. These cannot be stopped or resumed, but might be (possibly) executed on a different thread. In any case, they are not guaranteed to be executed immediately in the normal flow of the code.
>Ehm, not sure I understood, but I'd say no. Defer is just code that is executed in reverse order upon return from a fuction.
I'd say more like the equivalent of a "finally" clause (or more) for your whole function.
Though not sure about the "executed in reverse order part" -- what's "in reverse order" about Defer? Except if you mean that multiple defers get executed "last seen first"...
defer can refer to and change the return values. This is useful, for example, when the deferred code can trigger an error that one wants to return, https://play.golang.org/p/MBmy9OocAG
Is that actually returning err as the deferred return value of test? In other words, to the caller of test it appears test returns the result of the deferred?
Deferred functions don't return anything. You can modify the values that are returned by the parent function, and those will be returned as the deferred function modified them.
Yep, and one cannot simulate that with local variables. In Go "return v" copies v into the return location before calling the deferred code. If that location is not named, the deferred function has no way to change it, see https://play.golang.org/p/Opg4XI08P7
I got it. That's a neat example. Do you have to define that deferred function inside the caller, in order to reference the name? Or can you factor out deferred functions to be used by various callers and pass in the return names for them to modify?
Named returns are a Go thing mainly because of defer.