当前位置: 首页 > news >正文

快速了解 GO之 Defer 延迟操作

更多个人笔记见:
github个人笔记仓库
gitee 个人笔记仓库
个人学习,学习过程中还会不断补充~ (后续会更新在github上)

文章目录

  • Defer延迟操作
    • 基础知识
    • 基础案例
        • 多个defer倒着执行的顺序
        • defer返回数值问题
    • defer 的作用
        • 资源释放
        • 异常捕获
        • 中间件的一中实现方式
        • 参数预计算
        • defer返回数值问题

Defer延迟操作

基础知识

defer一般用于资源释放和异常捕获
defer有三种:堆上,栈上以及内联 内联相当于代码放到函数最后执行
defer必须掌握7ge

基础案例

多个defer倒着执行的顺序
func main() {for i:= 1;i<5;i++{defer fmt.Println("start",i)}//start 4//start 3//。。。
}

从后面的开始往前

defer返回数值问题

defer 的作用

资源释放
func CopyFile(srcName, dstName 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()// written, err = io.Copy(dst, src) //第一个参数是写入部分,这个直接return// dst.Close() //如果没有defer中间有问题,就不会执行close了// src.Close()return io.Copy(dst, src)
}

defer close 类的

异常捕获

用于打印:

func excute() {defer fmt.Println("defer func")panic("this is a panic")fmt.Println("completed")
}
func main() {excute()fmt.Println("main func") //main函数也将不能运行
}

或者recover 接收 panic:

func excute() {defer func() {if errMsg := recover(); errMsg!= nil {  //用recover接收fmt.Println(errMsg)fmt.Println("this is a recovery function")}}()panic("this is an error")fmt.Println("completed")
}
func main(){excute()fmt.Println("main function completed")  //可以正常执行
}
中间件的一中实现方式
package mainimport ("fmt""log""net/http"
)func recoverHandler(next http.Handler) http.Handler { //需要配合handle的类型fn := func(w http.ResponseWriter, r *http.Request) { //签名与 http.HandlerFunc 的定义完全一致:defer func() {if err := recover(); err != nil {log.Printf("panic:%v", err)http.Error(w, http.StatusText(500), 500)} else{next.ServeHTTP(w, r) //调用对应的ServeHTTP方法,再打印helloworld}}()next.ServeHTTP(w, r) //调用对应的ServeHTTP方法,这里是打印helloworld}return http.HandlerFunc(fn) //转换为 http.Handler 类型.fn 是一个符合 http.HandlerFunc 签名的函数就可以//由于HandlerFunc实现了ServeHTTP方法,所以 http.HandlerFunc(fn) 就是一个实现了 http.Handler 接口的实例!!!}type MyHandler struct{}// 定义MyHandler结构体的ServerHTTP方法,接收一个http.ResponseWriter和一个http.Request作为参数
func (m MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {// 将字符串"hello world"写入http.ResponseWriterfmt.Fprintf(w, "hello world")
}// 主函数
func main() {// 创建一个MyHandler实例handler := MyHandler{}// 创建一个http.Server实例,指定地址和处理器server := http.Server{Addr:    ":8080",Handler: recoverHandler(handler),}// 启动服务器server.ListenAndServe()
}
参数预计算

会在执行到的时候计算

func main() {a := 1defer func(b int) {//首先预编译执行fmt.Println("defer b:", b)}(a + 1)a = 99
}
defer返回数值问题
  • 结合全局变量和局部变量的存放问题理解,全局存在堆上,局部存在函数栈上
  • 先return?先defer? ->先 return 再 defer
    看下面两个例子对比:
var g = 100 //全局变量
func f() (r int){defer func(){g = 200  //对全局变量进行赋值} ()fmt.Printf("f:g = %d\n",g)  //\n换行符//f:g = 100return g
}func main() {i:=f()fmt.Printf("main:i = %d,g = %d\n",i,g)//main:i = 100,g = 200
}
//流程
//g = 100
//r = g=100 (r就是return的)
//g = 200
// return 得到r

以及

//另外一种可能:
var g = 100 //全局变量
func f() (r int){r = gdefer func(){r = 200}()r = 0return r
}func main() {i := f()fmt.Printf("main:i = %d, g = %d\n",i,g)//main:i = 200, g = 100  //上一个例子中就是i是100 
}
//流程:
// g = 100 //全局变量
// r = g = 100
// r = 0
// r =200
// r = r返回

本质是:返回值return(r)不是全局变量,所以存在栈上,执行defer函数后返回 (所以如果修改r就是可以体现的)

相关文章:

  • 拥塞控制算法cubic 和bbr
  • HTML流星雨
  • golang channel 的特点、原理及使用场景
  • 进行性核上性麻痹护理之道:助力患者舒适生活
  • (11)Service Mesh架构下Java应用实现零信任安全模型
  • Pycatia基础代码解析——零件设计篇(一)
  • 数字展厅建设需融合创意设计与实用功能,打造多维用户体验!
  • Unity性能优化
  • ClickHouse性能优化技术深度解析与实践指南
  • 【R语言编程绘图-函数篇】
  • 商城图片性能优化实战:懒加载与下一代格式的化学反应
  • 【Webtrees 用户手册】第 3 章 -会员指南
  • OpenSSL 与 C++ 搭建一个支持 TLS 1.3 的服务器
  • 迭代器和生成器
  • 【Linux】网络--传输层--TCP协议基础
  • Sparse VideoGen开源:完全无损,视频生成速度加速两倍,支持Wan 2.1、HunyuanVideo等
  • HarmonyOS NEXT~鸿蒙操作系统功耗优化特性深度解析
  • 【HarmonyOS 5应用架构详解】深入理解应用程序包与多Module设计机制
  • 5.26 面经整理 360共有云 golang
  • 鸿蒙OSUniApp 制作悬浮按钮与菜单组件#三方框架 #Uniapp
  • 诸城做网站/百度小说搜索风云榜排名
  • 哪有深圳设计公司/百度关键词优化技巧
  • 建立网站的目的是什么/查询网
  • wordpress翻页插件/广州优化公司哪家好
  • 海尔网站建设的目标是什么/网络推广产品公司
  • wordpress播客主题/百度快速优化软件