awesome-patterns/playground/defer/main.go

76 lines
2.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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")
}
// 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() {
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)
}
}
// The deferred func above will only run when the func ends not when the deferred funcs 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")
}
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 wouldnt be visible (Car.model). Because, the receiver is also an input param and evaluated immediately to “DeLorean DMC-12” when its
// 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"
}
func main() {
// nilFuncDefer()
// deferInsideLoop()
// block()
// deferStruct()
deferPointer()
}