• Go defer使用


    defer使用语法

    //defer后面必须是函数调用语句或方法调用语句,不能是其他语句,否则编译器会出错。
    package main
    import (
    	"fmt"
    )
    func foo(n int) int {
    	defer n++ 
    	//defer fmt.Println(n)
    	return n
    }
    func main() {
    	var i int = 100
    	foo(i)
    }
    
    # command-line-arguments
    expression in defer must be function call
    syntax error: unexpected ++ at end of statement
    

      

    defer 语句的用途

    含有 defer 语句的函数,会在该函数将要返回之前,调用另一个函数。

    defer后面的函数在defer语句所在的函数执行结束的时候会被调用;

    package main
    import (  
        "fmt"
    )
    
    type person struct {  
        firstName string
        lastName string
    }
    
    func (p person) fullName() {  
        fmt.Printf("%s %s",p.firstName,p.lastName)
    }
    
    func main() {  
        p := person {
            firstName: "John",
            lastName: "Smith",
        }
        defer p.fullName()
        fmt.Printf("Welcome ")  
    }

    在上面的程序里的第 11 行,a 的初始值为 5。在第 12 行执行 defer 语句的时候,由于 a 等于 5,因此延迟函数 printA 的实参也等于 5。接着我们在第 13 行将 a 的值修改为 10。下一行会打印出 a 的值。该程序输出:

    value of a before deferred function call 10  
    value of a in deferred function 5

    从上面的输出,我们可以看出,在调用了 defer 语句后,虽然我们将 a 修改为 10,但调用延迟函数 printA(a)后,仍然打印的是 5。

     

    defer 栈

    当一个函数内多次调用 defer 时,Go 会把 defer 调用放入到一个栈中,随后按照后进先出(Last In First Out, LIFO)的顺序执行。

    我们下面编写一个小程序,使用 defer 栈,将一个字符串逆序打印。

    package main
    import (  
        "fmt"
    )
    
    func main() {  
        name := "Naveen"
        fmt.Printf("Orignal String: %s
    ", string(name))
        fmt.Printf("Reversed String: ")
        for _, v := range []rune(name) {
            defer fmt.Printf("%c", v)
        }}
    Orignal String: Naveen
    Reversed String: neevaN
    

      

    defer 的实际应用

    • file对象打开后的自动关闭
    func CopyFile(dstName, srcName string) (written int64, err error) {
        src, err := os.Open(srcName)
        if err != nil {
            return
        }
        defer src.Close()
    
        dst, err := os.Create(dstName)
        if err != nil {
            return
        }
        defer dst.Close()
    
        // other codes
        return io.Copy(dst, src)
    }
    

     在打开输入文件输出文件后,不管后面的代码流程如何影响,这两个文件能够被自动关闭。 

    • mutex对象锁住后的自动释放
    func foo(...) {
        mu.Lock()
        defer mu.Unlock()
    
        // code logic
    }
    

    确保mu锁能够在函数foo退出之后自动释放。

    • WaitGroup的退出
    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
    ", r)
    		return
    	}
    	if r.width < 0 {
    		fmt.Printf("rect %v's width should be greater than zero
    ", r)
    		return
    	}
    	area := r.length * r.width
    	fmt.Printf("rect %v's area %d
    ", 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")
    }
    

      

     

  • 相关阅读:
    20189222 《网络攻防技术》第一周作业
    apue.h 运行UNIX环境高编程序
    fflush()函数
    线性链表如何选择二级指针还是一级指针
    scanf()gets()fgets()区别
    淺談Coach思考模式
    Hello World
    C语言I博客作业04
    python模块:logging
    python模块:subprocess
  • 原文地址:https://www.cnblogs.com/-wenli/p/11825433.html
Copyright © 2020-2023  润新知