2018-01-11 08:45:43 +03:00
package main
import "fmt"
// Sample code is taken from online tutorial https://blog.learngoprogramming.com/gotchas-of-defer-in-go-1-8d070894cb01
// it demostrate all the common GOTCHA when using defer.
// If a deferred func evaluates to nil, execution panic when surrounding func ends not when defer is called
func nilFuncDefer ( ) {
var run func ( ) = nil
defer run ( )
fmt . Println ( "runs" )
}
2018-01-12 07:27:12 +03:00
// Do not use defer inside a loop unless you are sure about what you are doing. It may not work as expected.
// However, in some situations it will be handy for instance,delegating the recursivity of a func to a defer.
func deferInsideLoop ( ) {
2018-01-12 08:02:10 +03:00
nums := [ ] int { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 }
for _ , v := range nums {
defer func ( v int ) {
fmt . Println ( v )
} ( v )
}
2018-01-12 07:27:12 +03:00
}
2018-01-12 08:08:16 +03:00
// The deferred func above will only run when the func ends not when the deferred func’ s surrounding block ends
// (the area inside curly braces containing the defer call). As seen in the example code, you can create separate blocks just using curly braces.
func block ( ) {
{
defer func ( ) {
fmt . Println ( "block: defer runs" )
} ( )
}
fmt . Println ( "main: ends" )
}
2018-01-12 08:31:09 +03:00
type Car struct {
model string
}
func ( c Car ) PrintModel ( ) {
fmt . Println ( c . model )
}
type Dog struct {
name string
}
func ( d * Dog ) MakeSound ( ) {
fmt . Println ( "WOFF my name is" , d . name )
}
// So, when a method with a value-receiver is used with defer, the receiver will be copied (in this case Car) at the time of
// registering and the changes to it wouldn’ t be visible (Car.model). Because, the receiver is also an input param and evaluated immediately to “DeLorean DMC-12” when it’ s
// registered with the defer.
func deferStruct ( ) {
c := Car { model : "model 1211" }
defer c . PrintModel ( )
c . model = "model 2018"
}
// Remember that the passed params to a deferred func are saved aside immediately without waiting the deferred func to be run.
func deferPointer ( ) {
d := & Dog { name : "James" }
defer d . MakeSound ( )
d . name = "Ann"
}
2018-01-11 08:45:43 +03:00
func main ( ) {
2018-01-12 08:02:10 +03:00
// nilFuncDefer()
2018-01-12 08:08:16 +03:00
// deferInsideLoop()
2018-01-12 08:31:09 +03:00
// block()
// deferStruct()
deferPointer ( )
2018-01-11 08:45:43 +03:00
}