This is a creation in Article, where the information may have evolved or changed.
Conclusion:
The closure function can directly refer to the variables defined by the outer code.
Note, however, that the address of the variable is referenced in the closure function,
When Goroutine is dispatched, the value of the address is passed to the Goroutine function.
Introduced
The closure of Go is a very useful thing. But if you don't know how a closure works, he will also bring you a bunch of bugs. Here I'm going to take out part of the code for the Go in action book and say a hole that you might encounter when using closures. The entire code is on GitHub.
Closed-Bag Pits
First look at a piece of code:
search/search.go// Launch a goroutine for each feed to find the results.for _, feed := range feeds {// Retrieve a matcher for the search.matcher, exists := matchers[feed.Type]if !exists { matcher = matchers["default"]}// Launch the goroutine to perform the search.go func(matcher Matcher, feed *Feed) { Match(matcher, feed, searchTerm, results) waitGroup.Done()}(matcher, feed)}
This code starts from 30 lines to traverse the slice of a feed. The value of the feed variable declared in the For Range statement is different in every loop. The code after the 32 line checks whether a particular key value has a value and assigns a default value if it does not exist. As with feed variables, the value of Matcher is different for Each loop.
Now we can jump to 38 rows to 41 rows. These lines of code are obviously still in the for Range loop. Here we define an anonymous function and run the function as a goroutine. This anonymous function accepts two parameters, the first is the value of the Matcher type, and the second is a pointer to the feed type. On the ground 41 lines, we can egg knife matcher and feed two variables are passed into the anonymous function.
This anonymous function is interesting in the implementation of line 39th. Here we can see a call to the match method. This method takes 4 parameters, and if you look closely, the first two parameters are the two parameters that we define for the anonymous function declaration. The latter two are not declared in the anonymous function. Instead, it is used as a variable directly in the anonymous function.
search/search.go// Launch the goroutine to perform the search.go func(matcher Matcher, feed *Feed) { Match(matcher, feed, searchTerm, results) waitGroup.Done()}(matcher, feed)}
Variables searchterm and results are defined outside the closure. We can use it directly inside the anonymous function without having to pass it in as a parameter. Here's a question: Why should we pass the variable matcher and feed as parameters and the other two?
I pointed out at the outset how the values of the two variables of the matcher and feed are changed in each for Range loop. The values of searchterm and results do not change with the loop, their values are constant for each goroutine life cycle. Of course, this goroutine is the anonymous function used. So why do you do that?
When we use a variable in an anonymous function closure, we do not have to pass it as a parameter when the anonymous function is declared. This anonymous function closure can directly access variables that are defined outside of it, meaning that changes to this variable are reflected inside the anonymous function closure, which is the goroutine. If we use matcher and feed variables like this, instead of passing them as arguments to the anonymous function closure. In most cases gotoutine will only process the last value of the For Range loop.
In this example, all goroutine will be executed concurrently. The For Range loop may run out when the first up to a second goroutine is running, and the matcher and feed variables will only have the value of the last loop. That is, even if not all goroutine are the same value that most goroutine will handle for these variables. This applies to searchterm and results variables, because they do not change values in the loop.
Conclusion
Fortunately, we can declare anonymous functions that can receive parameters, and these types of closure problems are also solved by an edge. In our example above, when each anonymous function is declared within the scope of the for range, the values of the matcher and feed variables are locked at the same time as the arguments passed into the anonymous function closure. When you use closures to access external variables, ask yourself how this variable will change, and how this change affects the operation of the closure.
Reference:
Http://devs.cloudimmunity.com/gotchas-and-common-mistakes-in-go-golang/index.html#closure_for_it_ VARs
http://studygolang.com/articles/7994
http://studygolang.com/articles/4738
http://blog.csdn.net/ htyu_0203_39/article/details/50985187
http://studygolang.com/articles/356
http://www.jb51.net/article/ 74166.htm
http://www.cnblogs.com/yjf512/archive/2012/12/09/2810313.html
https://www.zhihu.com/question/ 49341044?from=profile_question_card
Http://www.jb51.net/article/81813.htm