提问人:Greg T. Wallace 提问时间:8/9/2023 更新时间:8/9/2023 访问量:58
什么时候在 Golang 的匿名函数中声明变量?
When do you declare variables in anonymous functions in Golang?
问:
我在代码中使用了一些匿名函数,并试图了解在函数中调用的这两个代码snipet之间的区别(如果有的话):
defer func(s *Service, ID string) {
err := s.Deprovision(ID)
if err != nil {
s.logger.Error(err)
}
}(service, identifier)
defer func() {
err := service.Deprovision(identifier)
if err != nil {
service.logger.Error(err)
}
}()
一个直接使用父函数中可用的变量,另一个实质上是在匿名函数中声明这些变量,然后指定要传入的父变量。
这有什么不同吗?如果是这样,我什么时候需要注意这一点?
答:
您提供的两个代码片段都使用带有语句的匿名函数。但是,它们在如何捕获和使用封闭函数中的变量方面有所不同。让我们分解这些差异,并讨论何时需要注意它们:defer
直接使用变量(第一个代码段):在第一个代码片段中,匿名函数直接使用参数,并且来自封闭函数的作用域。这意味着这些变量由闭包捕获,可以直接在匿名函数中访问,而无需作为参数传递。
s
ID
将变量作为参数传递(第二个代码段):在第二个代码片段中,匿名函数不使用封闭函数作用域中的参数。相反,它从封闭函数的作用域中按值捕获 and 变量,然后在函数体中使用它们。这实质上等同于在匿名函数中声明和初始化新的局部变量。
service
identifier
这有什么不同吗?
是的,这两种方法之间存在差异,它们之间的选择取决于您的特定用例。
范围界定和清晰度:第一种方法更明确,对于阅读代码的人来说可能更清楚,因为它准确地显示了封闭作用域中正在使用哪些变量。这有助于防止潜在的错误并提高代码的可读性。
性能和内存:第二种方法(按值捕获变量)对性能和内存使用的影响很小,尤其是在封闭函数的作用域包含大型对象的情况下。这是因为每个闭包都有自己的捕获变量副本,这可能会增加内存消耗。
何时要注意:
变量更改:如果变量的值(在您的例子中)在定义匿名函数之后但在执行之前(由于循环或其他控制结构)发生更改,则第二种方法的行为可能是意外的。
service
identifier
闭包和 Goroutines:当将 goroutines 与闭包结合使用时,捕获的变量可能会对并发行为产生微妙的影响。确保您了解闭包如何捕获变量以及它们如何影响并发执行。
性能注意事项:如果内存使用是一个问题,或者按值捕获会导致性能问题,则可能需要考虑第一种方法,即直接使用现有变量。
在大多数情况下,这两种方法之间的差异可能并不显着,但在做出选择时了解这些注意事项是件好事。选择最适合您的特定用例并提高代码清晰度和可维护性的方法。
评论
defer
service
identifier
defer
*Service
defer