mirror of
https://github.com/crazybber/awesome-patterns.git
synced 2024-11-22 20:56:02 +03:00
76 lines
2.0 KiB
Go
76 lines
2.0 KiB
Go
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 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")
|
||
}
|
||
|
||
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"
|
||
}
|
||
|
||
func main() {
|
||
// nilFuncDefer()
|
||
// deferInsideLoop()
|
||
// block()
|
||
// deferStruct()
|
||
deferPointer()
|
||
}
|