golang中defer的使用 @ 胡巴 | 星期四,二月 17 日,2022 年 | 2 分钟阅读 | 更新于 星期四,二月 17 日,2022 年

golang中defer好像一个栈一样,在其后声明的表达式会被先行压入“栈”中,然后按照先进后出的顺序在真正return之前进行执行。

什么是真正return?golang中的return不是原子的,它可以分为三个部分执行:1.给返回值进行赋值 2.按照后进先出的顺序执行defer表达式 3.函数返回

package main

import "fmt"

// defer作用
// 1. 释放资源
// 2. 关闭连接
// 3. 做recover处理
func main() {
	deferStack()
	fmt.Println()
	fmt.Println(returnNotAtomic(1)) // 2
	fmt.Println()
	reference()
	deferFuncReturnWillDrop()
	fmt.Println()
	fmt.Println(Test1())
	fmt.Println()
	fmt.Println(Test2())
	fmt.Println()
	Test3()
	fmt.Println()
	Test4()
}

// 为什么是4 3 2 1 0?
// defer --> 栈 --> 先进后出
func deferStack() {
	for i := 0; i < 5; i++ {
		defer fmt.Println(i)
	}
	// 4
	// 3
	// 2
	// 1
	// 0
}

// golang中return 不是原子的
// return的执行分为三步
// 1. 给返回值赋值
// 2. 执行defer
// 3. return
func returnNotAtomic(a int) (ret int) {
	defer func() {
		ret++
	}()

	return a

//	ret = a
//	func () {
//		ret++
//	}
//	return
}

func reference() {
	for i := 0; i < 5; i++ {
		defer func() {
			// 这里的i是对for中i的一个引用
			// 所以在所有defer执行时,i已经变成了5
			// 最终输出 5 5 5 5 5
			fmt.Println(i)
		}()
	}
}

// defer表达式中若又返回值,将会被丢弃
func deferFuncReturnWillDrop() {
	defer func() (int) {
		return 1
	}()
}

func Test1() (r int) {
	t := 5
	defer func() {
		t = t + 5
	}()

	return t
	// r = t 即 r=5
	// defer t = t + 5 t=10
	// return 此时r=5
}

func Test2() (r int) {
	defer func(r int) {
		r = r + 5
	}(r)

	return 1
	// return_r = 1
	// defer return_r被以值拷贝的方式传入,里面的r和外面的r不是一个r
	// return return_r 的值没有被改变, 所以还是1
}

func deferExec(sli *[]int) {
	fmt.Println(sli)
}

// 最终三个输出结果都是&[5, 6]
func Test3() {
	sli := make([]int, 0)
	defer deferExec(&sli)
	sli = append(sli, 5)
	defer deferExec(&sli)
	sli = append(sli, 6)
	defer deferExec(&sli)

	return
}

type Test struct {
	Max int
}
func (t *Test) Println() {
	fmt.Println(t.Max)
}
func deferExec1(f func()) {
	f()
}
func Test4() (t *Test) {
	// t = nil
	defer deferExec1(t.Println) // 此时传入的t=nil

	//t = new(Test)
	t = &Test{
		Max: 1,
	}
	return
}

公众号: 无限递归

alt 搜索公众号:无限递归

Copyright © 2017 - 2024 boboidea.com All Rights Reserved 波波创意软件工作室 版权所有 【转载请注明出处】

avatar
基本信息
  • 姓名:bobo
  • 花名:胡巴
  • 性别:男
  • 血型:O型
  • 星座:白羊座

联系方式

  • 所在地:上海
  • QQ:279250819
  • 微信号:wanghuiwoshinideyou
  • 电子邮件:279250819@qq.com

博客地址

公众号

alt 无限递归

工作经历
  • 2022.5 - 至今

    • 公司:乐府互娱
    • 职位:高级SDK工程师
  • 2019.6 - 2022.4

    • 公司:萌推(上海突进网络科技有限公司)
    • 职位:中级PHP工程师 & 初级golang工程师
    • 荣誉:
      • 绩效A连续得主
      • 月度之星
      • 优秀个人奖
    • 所作所为:
      • 利用ES优化OMS、MMS管理系统商品列表查询
      • 利用消息队列、Redis、乐观锁优化商品审核流程
      • 利用Redis对商家端接口进行有效限流
      • 优化商品相关表索引,提升SQL查询速度
      • 商品中台构建,统一商品相关操作
      • 大表优化(数据分离、分表、大字段拆分)
      • 掌握所有商品核心流程
  • 2018.5 - 2019.5

    • 公司:DaDa英语(上海卓赞教育信息科技有限公司)
    • 职位:中级PHP开发工程师
    • 荣誉:无
    • 所作所为:
      • 利用ES优化教师CMS系统统计数据接口至500ms内
      • 工单系统开发及持续优化
      • 教师CMS系统的功能开发及持续优化
  • 2018.3 - 2018.5

    • 公司:波奇(上海)信息科技有限公司
    • 职位:初级PHP开发工程师
    • 荣誉:同下
    • 所做作为:如下
  • 2016.7 - 2018.3

    • 公司:光橙(上海)信息科技有限公司
    • 职位:初级PHP开发工程师
    • 荣誉:
      • 年度最佳进步奖
    • 所作所为:
      • 利用Redis提升商详接口最佳响应速度至50ms内
      • 利用Redis提升双11活动页可承受QPS至500以上
      • 利用Redis对接口进行简单限流
      • 与小伙伴合作提升搜索质量(ES初识)
      • 其他C端接口的开发及优化
      • B端商城老页面的维护及优化
SKILLS

编程语言

  • PHP
  • Golang
  • Shell
  • JAVA
  • JS
  • HTML\CSS

数据库

  • MySQL
  • Redis
  • Clickhouse

消息中间件

  • RabbitMq
  • Kafka

文档撰写

  • Swagger
  • Markdown

技术框架

  • Laravel
  • gin

搜索引擎

  • ElasticSearch

抓包工具

  • Charles