zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    UVA 1025 A Spy in the Metro DP水题
    ZOJ 3814 Sawtooth Puzzle BFS
    ZOJ 3816 Generalized Palindromic Number
    UVA 10859 Placing Lampposts 树形DP
    UVA 11825 Hackers' Crackdown 状压DP
    POJ 2887 Big String 线段树 离线处理
    POJ 1635 Subway tree systems Hash法判断有根树是否同构
    BZOJ 3110 k大数查询 & 树套树
    sdoi 2009 & 状态压缩
    来自于2016.2.24的flag
  • 原文地址:https://www.cnblogs.com/bonelee/p/6861777.html
Copyright © 2011-2022 走看看