Defer delay mechanism in Go language

    In Go language, sometimes it is necessary to delay processing a certain method, function or parameter, then the defer keyword is needed.

The effect of defer delay

1. Delay function

  • You can add multiple defer statements in the function.
    1) When the function is executed to the end, these defer statements will be executed in reverse order, and finally the function returns. Especially when you are doing some operations to open resources, you need to return in advance if you encounter errors. You need to close the corresponding resources before returning, otherwise it is easy to cause resource leakage and other problems;
    2) If there are many calls to defer, Then defer adopts the last-in-first-out mode;
    3) When leaving the method, execute defer itself (it will also execute when an error is reported)

    Case 1. In the main function of the delay call a function
//myDeferFuc.go support func A delay in main () in ()

// myDeferDes project main.go
package main

import (
	"fmt"
)

func funA() {
	fmt.Println("我是funA()...")
}

func funB() {
	fmt.Println("我是funB()...")
}

func funC() {
	fmt.Println("我是funC()...")
}

func main() {
	defer funA()
	funB()
	funC()
	fmt.Println("main is over...")
}


    The effect is as follows:


Figure (1) Delayed execution of func A() in main()

    Case 2. Functions delay call a function
//myDeferFunc2.go delay in the implementation of func finished in Functions ()

// myDeferMax project main.go
package main

import (
	"fmt"
)

func finished() {
	fmt.Println("结束!")
}

func largest(s []int) {
	defer finished()
	fmt.Println("开始寻找最大数...")
	max := s[0]
	for _, v := range s {
		if v > max {
			max = v
		}
	}
	fmt.Printf("%v中的最大数为:%v\n", s, max)
}

func main() {
	s1 := []int{78, 109, 2, 563, 300}
	largest(s1)
}


    The effect is as follows:


Figure (2) Delay calling func finished() in the sub-function

Second, the delay method

  • You can use defer to delay the call of a method

    Case 3. Delay calling a method in the main function
//myDeferMethod.go

// myDeferMethod project main.go
package main

import (
	"fmt"
)

type person struct {
	firstName string
	lastName  string
}

func (per person) fullName() {
	fmt.Printf("%s %s\n", per.firstName, per.lastName)
}

func main() {
	per := person{"Steven", "Wang"}
	defer per.fullName()
	fmt.Printf("Welcome, ")
}


    The effect is as follows:


Figure (3) Delay the call of the fullName() method in the main function

Three, delay parameter transfer (retain parameters)

  • Defer will retain the parameters before its declaration, and will execute at the end of the function.

    Case 4. Keep parameters a and b, use defer
//myDeferMethod.go

// myDeferParam project main.go
package main

import (
	"fmt"
)

func printAdd(a, b int) {
	fmt.Printf("延迟函数中: 参数a,b分别为%d,%d, 两数之和为:%d\n", a, b, a+b)
}

func main() {
	a := 5
	b := 6
	defer printAdd(a, b) //延迟参数a,b的传递
	a = 10
	b = 7
	fmt.Printf("延迟函数执行前: 参数a,b分别为%d,%d, 两数之和为:%d\n", a, b, a+b)

}


    The effect is as follows:


Figure (4) defer will retain the parameters before it is declared, and will be executed at the end of the function

Fourth, the delay of the stack

  • When a function has multiple delayed calls, they are added to a stack and executed in Last In First Out (LIFO) order.

    Case 5. Using defer to achieve string reverse order
//myDeferReveser.go

// myDeferHeap project main.go
package main

import (
	"fmt"
)

func ReverseString(str string) {
	for _, v := range []rune(str) {
		defer fmt.Printf("%c", v)
	}
}

func main() {
	name := "StevenWang欢迎学习区块链"
	fmt.Println("原始字符串: ", name)
	fmt.Println("翻转后的字符串: ")
	ReverseString(name)
}


    The effect is as follows:


Figure (5) Reverse string

Five, delay an application

  • Recommend to use WaitGroup

    Case 6 Delay an application
//myDeferApp.go

// myDeferApp project main.go
package main

import (
	"fmt"
	"sync"
)

type rect struct {
	length int
	width  int
}

func (r rect) area(wg *sync.WaitGroup) {
	defer wg.Done()
	if r.length < 0 {
		fmt.Printf("rect %v's length should be greater than zero\n", r)
		return
	}

	if r.width < 0 {
		fmt.Printf("rect %v's width should be greater than zero\n", r)
		return
	}

	area := r.length * r.width
	fmt.Printf("rect %v's area %d\n", r, area)
}

func main() {
	var wg sync.WaitGroup
	r1 := rect{-67, 89}
	r2 := rect{5, -67}
	r3 := rect{8, 9}
	rects := []rect{r1, r2, r3}
	for _, v := range rects {
		wg.Add(1)
		go v.area(&wg)
	}
	wg.Wait()
	fmt.Println("All go routines finished executing")
}


    The effect is as follows:


Figure (6) Delay an application

Guess you like

Origin blog.csdn.net/sanqima/article/details/108910280