Control flow

defer will defer function execution on end of parent function but before parent returns

// output:
// End
// Start
func main() {
    defer fmt.Println("Start")
    fmt.Println("End")
}

Deferred functions run in LIFO Last In First Out

// output:
// End
// Middle
// Start
func main() {
    defer fmt.Println("Start")
    defer fmt.Println("Middle")
    defer fmt.Println("End")
}

Arguments evaluated at time defer is executed, not at time of called function execution

// output: start
func main() {
    a := "start"
    defer fmt.Println(a)
    a = end
}

Deferred function will be executed before panic:

// output
// start
// deferred
// panic: error happened
func main() {
    fmt.Println("start")
    defer fmt.Println("deferred")
    panic("error happened")
}

panic stops function execution on exactly place where called. In the next example "stop panic" wouldn't be printed

// Output:
// start
// about to panic
// Error: Error happened
// end
func main() {
    fmt.Println("start")
    panicker()
    fmt.Println("end")
}

func panicker() {
    fmt.Println("about to panic")
    defer func(){
        if err := recover(); err != nil {
            log.Println("Error: ",err)
        }
    }()
    panic("Error happened")
    fmt.Println("stop panic")
}

there is recover function that can be used to recover from panics. Only useful in deferred functions(because they are executed right before panic)