Go 延迟调用机制

  defer延迟调用机制

是什么?为什么?

延迟调用是函数return正常结束后或者painc异常结束前会执行的一些操作。

再申请资源的时候延迟调用,防止忘记资源释放,数据库、文件、锁等资源释放。

延迟调用的顺序?

会按先进后出的顺序执行。

defer的值什么时候传递的?对外部变量如何引用?

defer定义时值就传递给defer了。

defer定义时对外部变量引用有两种方式:函数参数、闭包引用  

func main() {
	n := 3
	defer fmt.Println(n)
	n = 5
}
type number int

func (n number) print()   { fmt.Println(n) }
func (n *number) pprint() { fmt.Println(*n) }
func main() {
	var n number
	defer n.print()
	n = 3
}

/*
	defer n.print()
	defer n.pprint()
	defer func() { n.print() }()
	defer func() { n.pprint() }()
*/

defer_使用

func main() {
	defer fmt.Println("函数退出前执行")
}

defer_特性多个defer的执行顺序

func main() {
	defer fmt.Println("顺序 1")
	defer fmt.Println("顺序 2")
	defer fmt.Println("顺序 3")
}

//结果
/*
顺序 3
顺序 2
顺序 1
 */

 defer_return xxx 的注意事项

执行顺序
return ***
defer
return 

func f() int {
	r := 5
	defer func() { r += 5 }()
	return r
}
func main() {
	fmt.Println(f())
}

func f() (r int) {
	t := 5
	defer func() { t += 5 }()
	return t
}
func main() {
	fmt.Println(f())
}
func f() (r int) {
	r = 5
	defer func() { r += 5 }()
	return
}
func main() {
	fmt.Println(f())
}

defer_应用释放资源

打开文件

func main() {
	file, err := os.Open("example.txt") //打开文件
	if err != nil {
		fmt.Println("Error opening file:", err)
		return
	}
	defer file.Close() // 在函数结束前确保文件被关闭

	//对文件的操作
	//...

	// 这里不需要显式关闭文件,defer 会在函数结束时调用 file.Close()
}

http请求

func main() {
	// 发起 HTTP GET 请求
	resp, err := http.Get("https://jsonplaceholder.typicode.com/posts/1")
	if err != nil {
		fmt.Println("Error fetching data:", err)
		return
	}
	defer resp.Body.Close() // 确保在函数结束时关闭 HTTP 响应体

	// 读取响应的内容
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("Error reading response body:", err)
		return
	}

	fmt.Println("Response:", string(body))
}

defer_应用事务回滚

func performDatabaseOperation() error {
	db, err := sql.Open("mysql", "username:password@tcp(localhost:3306)/dbname")
	if err != nil {
		return err
	}
	defer db.Close() // 确保在函数结束时关闭数据库连接

	// 开始数据库事务
	tx, err := db.Begin()
	if err != nil {
		return err
	}
	defer func() {
		if p := recover(); p != nil {
			fmt.Println("Recovering from panic:", p)
			tx.Rollback() // 如果出现 panic,回滚事务
			panic(p)      // 继续传播 panic
		}
	}()

	// 在事务中执行一些操作
	_, err = tx.Exec("INSERT INTO table_name (column_name) VALUES (?)", "some value")
	if err != nil {
		tx.Rollback() // 发生错误时回滚事务
		return err
	}

	// 在函数结束时提交事务
	defer tx.Commit()

	// 模拟某些可能触发 panic 的操作
	// panic("something went wrong")

	return nil
}

相关推荐

  1. Go 延迟调用机制

    2024-06-05 19:36:18       9 阅读
  2. go延迟执行和定时器实现

    2024-06-05 19:36:18       38 阅读
  3. Go的两阶段延迟执行

    2024-06-05 19:36:18       29 阅读
  4. Go HTTP 调用(下)

    2024-06-05 19:36:18       38 阅读
  5. Go HTTP 调用(上)

    2024-06-05 19:36:18       31 阅读
  6. go垃圾回收机制

    2024-06-05 19:36:18       10 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-05 19:36:18       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-05 19:36:18       20 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-05 19:36:18       20 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-05 19:36:18       20 阅读

热门阅读

  1. Python实现连连看4

    2024-06-05 19:36:18       7 阅读
  2. 【golang】go语言读取Excel表格中的数据

    2024-06-05 19:36:18       8 阅读
  3. Go GORM中的迁移系统,实现自动迁移与手动迁移

    2024-06-05 19:36:18       10 阅读
  4. 深度学习-离线下载链接

    2024-06-05 19:36:18       9 阅读
  5. 什么叫硬编码?如何避免硬编码

    2024-06-05 19:36:18       10 阅读
  6. 字符串逆序数据结构

    2024-06-05 19:36:18       10 阅读
  7. MySQL的一些高频面试题汇总(持续补充)

    2024-06-05 19:36:18       9 阅读
  8. 富格林:掌握正规甄别欺诈信息

    2024-06-05 19:36:18       9 阅读
  9. FFmpeg中视频 Filters 使用文档介绍

    2024-06-05 19:36:18       14 阅读
  10. 汽车电子专栏目录一览

    2024-06-05 19:36:18       10 阅读
  11. stm32和esp32硬件资源上有什么区别

    2024-06-05 19:36:18       8 阅读