Go defer 去掉闭包函数及用法分析

 更新时间:2023年07月13日 09:51:50   作者:煎鱼  
这篇文章主要为大家介绍了Go defer 去掉闭包函数及用法分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

引言

在 Go 语言里,defer 关键字是大家很爱用的。因为他有着 defer+recover+panic 的组合拳打法,还有种各种 defer close 等常用场景。

defer 常见用法

在语法上,Go defer 的代码示例如下:

package main
import "fmt"
func main() {
    defer fmt.Println("煎鱼你好!")
    fmt.Println("放学别走")
}

输出结果:

放学别走
煎鱼你好!

那 defer 在 Go 里的常见用法有哪些呢?首先是上文用到的,直接 defer + 函数:

defer f()

其次是 defer+闭包的方式:

defer func() { 
   result := f()
   // do something with result
}()

其他还有在面试题上常被考究的传参变形:

func f1() int {
    i := 1
    defer func() {
        i++
    }()
    ...
}
func f2() int {
    i := 1
    defer func(i int) {
        i++
    }(i)
    ....
}

这些代码看起来,我们总是在对 defer 做闭包的各种声明和使用。defer 会不会就是和闭包天生一对?

新提案:defer 代码块

最近大家也在讨论一个与之相关的 Go 提案《proposal: Go 2: deferred code blocks》,由 @Damien Lloyd 提出,想看看有没有机会把 defer 的新语法落地。

原作者在使用 defer 时也是经常:

defer f()

但这样就无法获得返回值。最终要变成:

defer func() { 
   result := f()
   // do something with result
}()

基于上述类似的原因,想引入如下具有 defer 作用的代码块语法:

defer {
   // 在封闭函数的末尾执行此操作
}

在使用了 defer 关键字的函数最后执行这整个代码块 {...}。代码块中的每一行将按顺序运行。

作者给出的代码示例:

func fn() {
    f, err := os.Create("eddycjy.txt")
    if err != nil {
        panic(err)
    }
    defer {
       err := f.Close()
       if err != nil {
          panic(err)
       }
    }
}

在 fn 函数,声明了 defer {...},代码块内是对 f.Close 的兜底判断和异常抛出。在函数结束后执行这整个代码块。

反对的声音

当然,这看着似乎是比较美好的。看起来原提案作者只是简化了 defer 是的闭包使用,调整了作用域的范围。

但在社区内其实遭受比较多的反对声音。包含但不限于:

1、收益比不高:这个提案只是避免了 func() 和 () 等闭包声明,但是却要增加新的 defer 语法(语言语法更改会带来高昂成本),这个变更的 ROI 不高。

2、破坏兼容性:原 defer 关键字调用总是会跟着函数的词法调用,有良好的一致性。如果进行修改,会产生新的隐晦,破坏一致性。也会对现有的许多工具(例如:静态分析工具)产生影响,全要改。

3、作用域问题:原本 defer func{}() 的代码块结构下,你的代码作用域都限于闭包函数下。而使用新的 defer {} 的结构,该返回和操作,是否应该会影响到外部函数的结果?(这是最有争议的一点,作者也比较前言不搭后语,没明确指明语法意思)

总结

一开始乍一眼一看,感觉只是把 defer 关键字语句简化一下,好像特别好,省了几个单词。就像 if err != nil 也会有提要用 Rust 的 ? 等用法来替代的。

经过社区网友们指出后,发现这里猫腻不少。一门已经有 10+ 年的编程语言,还有 Go1 兼容性保障的。做出这类带作用域的提案变更,是有比较大的风险的。

同时对于 Go 工具链的影响,也是非常大的。一改,直接都完犊子了。确实需要尽量深思。原作者完全没提到。

该提案,正在开放 3 周等待意见收集。很神奇,没更多的人说话,但提案的表情给了很多个不认同。

以上就是Go defer 去掉闭包函数及用法分析的详细内容,更多关于Go defer闭包函数的资料请关注脚本之家其它相关文章!

相关文章

  • 详解Golang中channel的实现

    详解Golang中channel的实现

    channel俗称管道,用于数据传递或数据共享,其本质是一个先进先出的队列,使用goroutine+channel进行数据通讯简单高效,同时也线程安全,本文就给大家讲讲Golang中channel的实现,需要的朋友可以参考下
    2023-09-09
  • 浅析Go中序列化与反序列化的基本使用

    浅析Go中序列化与反序列化的基本使用

    序列化是指将对象转换成字节流,从而存储对象或将对象传输到内存、数据库或文件的过程,反向过程称为“反序列化”。本文主要介绍了Go中序列化与反序列化的基本使用,需要的可以参考一下
    2023-04-04
  • golang的time包:秒、毫秒、纳秒时间戳输出方式

    golang的time包:秒、毫秒、纳秒时间戳输出方式

    这篇文章主要介绍了golang的time包:秒、毫秒、纳秒时间戳输出方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • GO语言实现文件上传代码分享

    GO语言实现文件上传代码分享

    本文给大家分享的是一则使用golang实现文件上传的代码,主要是使用os.Create创建文件,io.Copy来保存文件,思路非常清晰,这里推荐给大家,有需要的小伙伴参考下吧。
    2015-03-03
  • 详解Go语言的内存模型及堆的分配管理

    详解Go语言的内存模型及堆的分配管理

    这篇笔记主要介绍Go内存分配和Go内存管理,会轻微涉及内存申请和释放,以及Go垃圾回收,文中有详细的代码示例以及图片介绍,需要的朋友可以参考下
    2023-05-05
  • golang字符串转Time类型问题

    golang字符串转Time类型问题

    本文主要介绍了golang字符串转Time类型问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • 深入理解Go语言中的Dispatcher

    深入理解Go语言中的Dispatcher

    最近看到了Go语言中的Dispatcher,但是在网上发现资料非常少,所以想着总结处理分享给大家,下面这篇文章主要给大家深入的介绍Go语言中Dispatcher的相关资料,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-03-03
  • 深入理解gorm如何和数据库建立连接

    深入理解gorm如何和数据库建立连接

    这篇文章主要为大家详细介绍了gorm如何和数据库建立连接,文中的示例代码讲解详细,对我们深入了解GO语言有一定的帮助,需要的小伙伴可以参考下
    2023-11-11
  • golang中日期操作之日期格式化及日期转换

    golang中日期操作之日期格式化及日期转换

    在编程中,程序员会经常使用到日期相关操作,下面这篇文章主要给大家介绍了关于golang中日期操作之日期格式化及日期转换的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-11-11
  • Golang标准库unsafe源码解读

    Golang标准库unsafe源码解读

    这篇文章主要为大家介绍了Golang标准库unsafe源码解读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08

最新评论