在Golang中,你何时在匿名函数中声明变量?

huangapple go评论81阅读模式
英文:

When do you declare variables in anonymous functions in Golang?

问题

在你的代码中,我使用了一些匿名函数,并且我正在尝试理解在一个函数中调用这两个代码片段之间的区别(如果有的话):

第一个代码片段直接使用了父函数中可用的变量,并且在匿名函数中指定了要传入的父变量。

第二个代码片段则在匿名函数中声明了这些变量,并且指定了要传入的父变量。

这两种方式有什么区别吗?如果有的话,我需要在什么时候注意这个区别呢?

英文:

I use some anonymous functions in my code and I’m trying to understand the difference (if there is one) between these two code snipets being called in a function:

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)
	}
}()

One directly uses variables available in the parent func and the other essentially declares these variables in the anonymous function and then specifies the parent variables to pass in.

Does this make a difference? If so, when do I need to be mindful of this?

答案1

得分: 1

你提供的两个代码片段都使用了带有defer语句的匿名函数。然而,它们在捕获和使用来自封闭函数的变量方面存在差异。让我们分解这些差异,并讨论何时需要注意它们:

  1. 直接使用变量(第一个代码片段):
    在第一个代码片段中,匿名函数直接使用了封闭函数作用域中的参数sID。这意味着这些变量被闭包捕获,并且可以在匿名函数内部直接访问,而无需作为参数传递。

  2. 将变量作为参数传递(第二个代码片段):
    在第二个代码片段中,匿名函数不使用封闭函数作用域中的参数。相反,它通过值从封闭函数作用域中捕获了serviceidentifier变量,然后在函数体内使用它们。这本质上等同于在匿名函数内部声明和初始化新的局部变量。

这会有什么区别吗?

是的,这两种方法之间存在差异,选择取决于您的具体用例。

  • 作用域和清晰度:
    第一种方法更加明确,对于阅读代码的人来说可能更清晰,因为它明确显示了从封闭作用域中使用的变量。这有助于防止潜在的错误,并提高代码的可读性。

  • 性能和内存:
    第二种方法中,通过值捕获变量可能会对性能和内存使用产生轻微影响,特别是如果封闭函数作用域包含大型对象。这是因为每个闭包都会有自己的捕获变量副本,这可能会增加内存消耗。

需要注意的情况:

  1. 变量更改: 如果变量的值(在您的情况下是serviceidentifier)在匿名函数定义之后但在执行之前发生更改(由于循环或其他控制结构),第二种方法的行为可能是意外的。

  2. 闭包和Goroutines: 在与闭包结合使用Goroutines时,捕获的变量可能对并发行为产生微妙影响。确保您了解闭包如何捕获变量以及它们如何影响并发执行。

  3. 性能考虑: 如果内存使用是一个问题,或者通过值捕获导致性能问题,您可能希望考虑第一种方法,直接使用现有变量。

在大多数情况下,这两种方法之间的差异可能不太显著,但在选择时了解这些考虑因素是很好的。选择最适合您特定用例并促进代码清晰度和可维护性的方法。

英文:

The two code snippets you provided are both using anonymous functions with defer statements. However, they differ in how they capture and use variables from the enclosing function. Let's break down the differences and discuss when you need to be mindful of them:

  1. Direct Use of Variables (First Snippet):
    In the first code snippet, the anonymous function directly uses the parameters s and ID from the enclosing function's scope. This means that these variables are captured by the closure and can be accessed directly within the anonymous function without being passed as arguments.

  2. Passing Variables as Arguments (Second Snippet):
    In the second code snippet, the anonymous function does not use the parameters from the enclosing function's scope. Instead, it captures the service and identifier variables by value from the enclosing function's scope and then uses them within the function body. This is essentially equivalent to declaring and initializing new local variables within the anonymous function.

Does this make a difference?

Yes, there is a difference between the two approaches, and the choice between them depends on your specific use case.

  • Scoping and Clarity:
    The first approach is more explicit and may be clearer to someone reading the code, as it shows exactly which variables are being used from the enclosing scope. This can help prevent potential mistakes and improve code readability.

  • Performance and Memory:
    The second approach, where variables are captured by value, can have a small impact on performance and memory usage, especially if the enclosing function's scope contains large objects. This is because each closure will have its own copy of the captured variables, which could increase memory consumption.

When to Be Mindful:

  1. Variable Changes: If the values of the variables (service and identifier in your case) change after the anonymous function is defined but before it is executed (due to loops or other control structures), the behavior of the second approach might be unexpected.

  2. Closures and Goroutines: When using goroutines in conjunction with closures, the captured variables can have a subtle impact on concurrency behavior. Make sure you understand how closures capture variables and how they can affect concurrent execution.

  3. Performance Considerations: If memory usage is a concern or if capturing by value causes performance issues, you might want to consider the first approach, which directly uses the existing variables.

In most cases, the differences between the two approaches might not be significant, but it's good to be aware of these considerations when making your choice. Choose the approach that best fits your specific use case and promotes code clarity and maintainability.

huangapple
  • 本文由 发表于 2023年8月9日 00:22:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76861474.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定