1. Variable scope and visibility of functions
1. Global variables are initialized before the main function is executed and are visible globally
2. Local variables are valid inside the function or statement blocks such as if, for, etc., and cannot be visible outside after use.
3. When the global variable and local variable have the same name, local variables take effect.
4. Visibility:
Any variable or function in the package is accessible.
If outside the package, the initial letter can be accessed in capital, and the initial letter with lowercase means that private ones cannot be called externally.
2. Anonymous functions
Functions are also a type in language, so they can be received using a function-type variable.
func anonyTest1(){ ("anonyTest1") } // Assign the change function to a variable f and execute ffunc AnonyTest(){ f:= anonyTest1 f() }
2. Anonymous functions are functions that do not specify names. The following is the use of anonymous functions.
func AnonyTest2(){ f:= func() { ("AnonyTest2") } f() //or func() { ("AnonyTest2...") }() }
3. The following example combines defer to see what these three outputs are
func AnonyTest3(){ var i=0 defer func() { ("defer func i=%v \n",i) }() defer ("defer i=%v \n",i) for;i<10; i++{ } ("i=%v \n",i) }
From the article defer we know that defer ("defer i=%v \n",i) prints the value after i is initialized, and the last one must be the value after the for loop 10.
It mainly means the value after the anonymous function is executed, which is interestingly 10, which means that the i outside the anonymous function is accessed, which involves the closure.
The operation results are as follows:
i=10
defer i=0
defer func i=10
4. Since functions are also a type, you can input and output functions as parameters. (It feels a bit similar to the commission in C#)
func Calc(a,b int, op func(int,int)int) int { return op(a,b) } func add(a,b int) int{ return a+b } func sub(a,b int)int{ return a-b } func AnonyTest4(){ var a = 2 var b = 1 var x = Calc(a,b,add) var y = Calc(a,b,sub) ("x=%v, y=%v \n",x,y) }
result:
x=3, y=1
3. Closure
Closures are entities composed of functions and reference environments related to them (very abstract, difficult to understand)
func Adder() func(int) int{ var x int return func(d int) int{ x+=d return x } }
Like the above code, we can see that a variable x is defined, and an anonymous function in return. We can see that the anonymous function refers to the external variable x, and we can call this x a free variable.
In other words, this anonymous function and this free variable x form a whole, and this x is valid as long as it is in the life cycle of this whole.
Here is the Adder function:
func ClosureDemo5(){ var f = Adder() ("result=%d\n",f(1)) ("result=%d\n",f(20)) ("result=%d\n",f(300)) }
Execution results
Results = 1
Results = 21
Results = 321
As mentioned above, as long as Addr(), that is, the object f does not disappear, then the x in f will always exist, which is why the second time is 21 and the third time is 321.
Other examples:
Example 1:
func Adder2(base int) func(int)int{ return func(i int) int{ base += i return base } } func main(){ tmp1 := Adder2(10) (tmp1(1),tmp1(2)) tmp2 := Adder2(100) (tmp2(10),tmp2(20)) }
Here Adder2 receives an int-type parameter base, and then returns a func. This anonymous function refers to this parameter base, so this parameter base and the anonymous function form a whole.
Later, we are assigned tmp1 as Adder2(10) , so during the life cycle of the object tmp1, base is initialized to 10 and exists all the time, so the results are 11 and 13, and the same is followed by 110 and 130
Example 2:
func calc(base int) (func(int)int,func(int)int){ add:= func(i int)int{ base +=i return base } sub:= func(i int)int{ base -= i return base } return add,sub } func main(){ f1,f2 := calc(10) (f1(1),f2(2)) (f1(3),f2(4)) (f1(5),f2(6)) (f1(7),f2(8)) }
Let's analyze:
Here, the anonymous functions of base, add and sub also form an entity, calc, so during the life cycle of f1 and f2, base always exists and is initialized to 10.
So the result is that f1(1) is 10+1 =11 and f2(2) is 11-2 = 9, the same applies to others.
So the result is as follows:
11 9
12 8
13 7
14 6
Side effects of closure!
func main(){ for i:=0;i<5;i++{ go func(x int){ (x) }(i) } () }
What should be the result of the above code? My guess is 0, 1, 2, 3, 4
But the actual result is:
5
5
5
5
5
Why does this happen? In fact, the anonymous functions in each go coroutine and the i of the external for loop also form a closure. Because the for loop executes faster, go becomes 5 before it has time to execute.
I add a delay after each go coroutine, and the result is 0, 1, 2, 3, 4.
func main(){ for i:=0;i<5;i++{ go func(){ (i) }() () } () }
The results are as follows
0
1
2
3
4
The problem is that it is impossible to delay every execution, so one thing needs to be done to break this closure.
func main(){ for i:=0;i<5;i++{ go func(x int){ (x) }(i) } () }
Here, i is passed into an anonymous function as a parameter, ensuring that the value passed in each loop is different.
This is all about this article about Go language closures. I hope it will be helpful to everyone's learning and I hope everyone will support me more.