Details of golang closure instance

Keywords: Fragment

closure

concept

Closure function: a function declared in a function, called a closure function.

Closure: an internal function always has access to the parameters and variables declared in the external function in which it resides, even after its external function has been returned (end of life).

Characteristic

Make it possible for external access to function internal variables;

Local variables are resident in memory;

It can avoid the use of global variables and prevent the pollution of global variables;

Can cause memory leaks (a block of memory space is occupied for a long time without being released)

Closure creation

Closure is to create an independent environment. The environment in each closure is independent and does not interfere with each other. There will be a memory leak in the closure. * * each time the external function executes, the reference address of the external function is different, and a new address will be created again. **However, if the data in the current active object is referenced by an internal subset, at this time, the data will not be deleted and a

Closure example

Example 1

  • Returns an intrinsic function
package main

import "fmt"

//Function segment
func add(base int) func(int) int { // 1: Create a new memory, and name it base to store int variables. Then take the value stored in a memory, copy it and put it in base memory

	fmt.Printf("%p\n", &base)  //2: Print variable address 0xc0420080e0, which stores 10 [it is the function copy value]

	f := func(i int) int {  //3: Define a function and use f to point to it [f stores the address of this function]
	    //7. Store 1 in i
		fmt.Printf("%p\n", &base) // 2: Print variable address 0xc0420080e0
		base += i // Take out the value stored in the base + the value stored in the i, and then put the result into the base for storage
		return base //Return the value stored in the base
	}

	return f  // 4: Return function address f
}



func main() {
	aa := 10
	fmt.Printf("a Address:%p\n", &aa) //0xc0420080a8
	t1 := add(aa)                //5. Store the function address returned by add(a) with a t1
	c := t1(1)                   //6. Call the function pointed to by t1, pass the parameter as 1 [pass the value], and then store the returned result in the new memory c
	fmt.Println(c, &c)           //11 0xc0420540b0
	fmt.Println(t1(2))           // 13 T1 still points to the original open space. At this time, base=11, so 11 + 2

	t2 := add(100) //Open up a new space to call add(100), and then store the returned function address with a t2. At this time, base is the newly established
	fmt.Println(t2(1), t2(2))
}

  • Returns multiple intrinsic functions
package main

import "fmt"

//Return the addition and subtraction function, important: reference to external variable when internal function
func calc(base int) (func(int) int, func(int) int) {

	fmt.Printf("%p\n", &base)
	add := func(i int) int {
		fmt.Printf("%p\n", &base)
		base += i
		return base
	}

	sub := func(i int) int {
		fmt.Printf("%p\n", &base)
		base -= i
		return base
	}

	return add, sub
}

//Starting from main function as program entry point
func main() {
	f1, f2 := calc(11111)
	fmt.Println(f1(1), f2(1)) //Execution sequence: f1 f2 println
}

Example two

When goroutine is involved, the program fragment is as follows:

package main

import (
	"fmt"
	"time"
)

//Starting from main function as program entry point
func main() {

	for i:=0; i<5; i++ {
		go func(){
			fmt.Println(i) //The value of the i variable is also a reference. Create 5 thread execution functions. When the execution of the for loop may be completed, the thread just benefits a certain value of i.
		}()

	}
	time.Sleep(time.Second * 1)
}

Every time the program runs, the results are different

Code improvements:

package main

import (
	"fmt"
	"time"
)

func main() {

	ch := make(chan int, 1)

	for i:=0; i<5; i++ {
		go func(){
			ch <- 1
			fmt.Println(i)
		}()

		<- ch
	}
	time.Sleep(time.Second * 1)
}

Will block waiting: 0-4 value must have

Reference resources: https://blog.csdn.net/li_101357/article/details/80196650

Example three:

package main

import "fmt"

func funA() func(){
	var a = 10;
	return func (){
		fmt.Println(a); // Value stored at printing place a
	}
}


func main() {
	var b = funA() //funA() returns a function address, executes a function, and saves the address with b. at this time, b points to the function
	b() // Call the function pointed to by b
}

Example 4: global variable VS closure function

package main

import "fmt"

func Outer() func(){
	var i = 0;
	return func() {
		i++;
		fmt.Println(i)
	}
}

func main(){
	var c = Outer()
	c()
	c()
	c()

	var d = Outer()
	d()
	d()
	d()
}

// 1 2 3 1 2 3 
  • Global function
package main

import "fmt"

var i = 0;


func Outer() func(){

	return func() {
		i++;
		fmt.Println(i)
	}
}

func main(){
	var c = Outer()
	c()
	c()
	c()

	var d = Outer()
	d()
	d()
	d()
}
// 1 2 3 4 5 6 

Example six

package main

import "fmt"

func Outer() func() int{
	var i = 0;
	return func() int{
		 i++;
		 return i;
	}
}

func main(){
	c := Outer() // Returns a function
	fmt.Println(c()) //1 call the internal function, copy the value of i, and return
	fmt.Println(c()) //2 call the internal function, copy the value of i, and return

	d := c // c stores the function address. c places the stored function address in d. at this time, d and c point to the same function
	fmt.Println(d()) //3 call the internal function, copy the value of i, and return
	fmt.Println(d()) //4 call the internal function, copy the value of i, and return

	e := Outer() // A new memory is created to call functions. e stores the address of this memory
	fmt.Println(e()) //1 call the internal function, copy the value of i, and return
	fmt.Println(e()) //2 call the internal function, copy the value of i, and return

	fmt.Println(Outer()) //0x496a30
	fmt.Println(Outer()()) //1
}

Published 255 original articles, praised 71, visited 200000+
His message board follow

Posted by zako234 on Thu, 27 Feb 2020 23:31:39 -0800