• go语言笔记——defer作用DB资源等free或实现调试


    defer 和追踪

    关键字 defer 允许我们推迟到函数返回之前(或任意位置执行 return 语句之后)一刻才执行某个语句或函数(为什么要在返回之后才执行这些语句?因为 return 语句同样可以包含一些操作,而不是单纯地返回某个值)。

    关键字 defer 的用法类似于面向对象编程语言 Java 和 C# 的 finally 语句块,它一般用于释放某些已分配的资源。

    示例 6.8 defer.go

    package main
    import "fmt"
    
    func main() {
    	function1()
    }
    
    func function1() {
    	fmt.Printf("In function1 at the top
    ")
    	defer function2()
    	fmt.Printf("In function1 at the bottom!
    ")
    }
    
    func function2() {
    	fmt.Printf("function2: Deferred until the end of the calling function!")
    }

    输出:

    In Function1 at the top
    In Function1 at the bottom!
    Function2: Deferred until the end of the calling function!

    请将 defer 关键字去掉并对比输出结果。

    使用 defer 的语句同样可以接受参数,下面这个例子就会在执行 defer 语句时打印 0

    func a() {
    	i := 0
    	defer fmt.Println(i)
    	i++
    	return
    }

    当有多个 defer 行为被注册时,它们会以逆序执行(类似栈,即后进先出):

    func f() {
    	for i := 0; i < 5; i++ {
    		defer fmt.Printf("%d ", i)
    	}
    }

    上面的代码将会输出:4 3 2 1 0

    关键字 defer 允许我们进行一些函数执行完成后的收尾工作,例如:

    1. 关闭文件流:

      // open a file defer file.Close() (详见第 12.2 节)

    2. 解锁一个加锁的资源

      mu.Lock() defer mu.Unlock() (详见第 9.3 节)

    3. 打印最终报告

      printHeader() defer printFooter()

    4. 关闭数据库链接

      // open a database connection defer disconnectFromDB()

    合理使用 defer 语句能够使得代码更加简洁。

    使用 defer 语句实现代码追踪

    一个基础但十分实用的实现代码执行追踪的方案就是在进入和离开某个函数打印相关的消息,即可以提炼为下面两个函数:

    func trace(s string) { fmt.Println("entering:", s) }
    func untrace(s string) { fmt.Println("leaving:", s) }

    以下代码展示了何时调用两个函数:

    示例 6.10 defer_tracing.go:

    package main
    
    import "fmt"
    
    func trace(s string)   { fmt.Println("entering:", s) }
    func untrace(s string) { fmt.Println("leaving:", s) }
    
    func a() {
    	trace("a")
    	defer untrace("a")
    	fmt.Println("in a")
    }
    
    func b() {
    	trace("b")
    	defer untrace("b")
    	fmt.Println("in b")
    	a()
    }
    
    func main() {
    	b()
    }

    输出:

    entering: b
    in b
    entering: a
    in a
    leaving: a
    leaving: b

    使用 defer 语句来记录函数的参数与返回值——利用了defer是在return后的特性哇!!!

    下面的代码展示了另一种在调试时使用 defer 语句的手法(示例 6.12 defer_logvalues.go):

    package main
    
    import (
    	"io"
    	"log"
    )
    
    func func1(s string) (n int, err error) {
    	defer func() {
    		log.Printf("func1(%q) = %d, %v", s, n, err)
    	}()
    	return 7, io.EOF
    }
    
    func main() {
    	func1("Go")
    }
    

    输出:

    Output: 2011/10/04 10:46:11 func1("Go") = 7, EOF
  • 相关阅读:
    关于线程池,那些你还不知道的事
    Java发送邮件
    原来实现项目多环境打包部署是如此的简单
    史上最全的maven的pom.xml文件详解
    Linux系统基础知识整理(一)
    计算机启动过程的简单介绍 计算机启动流程 计算机BIOS作用 POST 开机自检 计算机启动顺序 分区表 操作系统启动
    交换机工作原理、MAC地址表、路由器工作原理详解
    $(function(){})和$(document).ready(function(){}) 的区别
    关于RAM与ROM的区别与理解
    CDN的作用与基本过程
  • 原文地址:https://www.cnblogs.com/bonelee/p/6861777.html
Copyright © 2020-2023  润新知