GO anonymous functions and closures

GO anonymous functions and closures

Anonymous function: As the name implies, it is a function without a name. There are many languages ​​such as: java, js, php, etc., among which js is the most favorite. The biggest use of anonymous functions is to simulate block-level scope and avoid data pollution.

Today I will mainly talk about anonymous functions and closures in the Golang language.

Anonymous function

Example:

1,

package main

import (
   "fmt"
)
func main() {
   f:=func(){
      fmt.Println("hello world")
   }
   f()//hello world
   fmt.Printf("%T\n", f)//Print func()
}

2. With parameters

package main

import (
   "fmt"
)
func main() {
   f:=func(args string){
      fmt.Println(args)
   }
   f("hello world")//hello world
  //or
   (func(args string){
        fmt.Println(args)
    })("hello world")//hello world
   //or
    func(args string) {
        fmt.Println(args)
    }("hello world")//hello world
}

3. With return value

package main

import "fmt"

func main() {
   f:=func()string{
      return "hello world"
   }
   a:=f()
   fmt.Println(a)//hello world
}

4. Multiple anonymous functions

package main

import "fmt"

func main() {
   f1,f2:=F(1,2)
   fmt.Println(f1(4))//6
   fmt.Println(f2())//6
}
func F(x, y int)(func(int)int,func()int) {
   f1 := func(z int) int {
      return (x + y) * z/2
   }

   f2 := func() int {
      return 2 * (x + y)
   }
   return f1,f2
}

Closure

Closure: To put it bluntly, it is the nesting of functions. The inner function can use all the variables of the outer function, even if the outer function has been executed.

Example:

1,

package main

import "fmt"

func main() {
    a := Fun()
    b:=a("hello ")
    c:=a("hello ")
    fmt.Println(b)//worldhello 
    fmt.Println(c)//worldhello hello 
}
func Fun() func(string) string {
    a := "world"
    return func(args string) string {
        a += args
        return a
    }
}

2,

package main

import "fmt"

func main() {
   a := Fun()
   d := Fun()
   b:=a("hello ")
   c:=a("hello ")
   e:=d("hello ")
   f:=d("hello ")
   fmt.Println(b)//worldhello
   fmt.Println(c)//worldhello hello
   fmt.Println(e)//worldhello
   fmt.Println(f)//worldhello hello
}
func Fun() func(string) string {
   a := "world"
   return func(args string) string {
      a += args
      return a
   }
}

Note that calling F() twice does not maintain the same a variable.

3.

package main

import "fmt"

func main() {
   a := F()
   a[0]()//0xc00004c080 3
   a[1]()//0xc00004c080 3
   a[2]()//0xc00004c080 3
}
func F() []func() {
   b := make([]func(), 3, 3)
   for i := 0; i <3; i++ {
      b[i] = func() {
         fmt.Println(&i,i)
      }
   }
   return b
}

Closures use external function variables by reference. In the example, function F is called only once to form a closure, i is defined in the external function B, so the closure maintains the variable i, i in a[0], a[1], and a[2] are all closed Reference to i in the package. Therefore, when executed, the value of i has become 3, so the output when a[0]() is called again is 3 instead of 0.

4. How to avoid the above BUG, ​​use the following method, pay attention to the comparison with the above example.

package main

import "fmt"

func main() {
    a := F()
    a[0]()//0xc00000a0a8 0
    a[1]()//0xc00000a0c0 1
    a[2]()//0xc00000a0c8 2
}
func F() []func() {
    b := make([]func(), 3, 3)
    for i := 0; i <3; i++ {
        b[i] = (func(j int) func() {
            return func() {
                fmt.Println(&j, j)
            }
        })(i)
    }
    return b
}
or
package main

import "fmt"

func main() {
    a := F()
    a[0]()//0xc00004c080 0
    a[1]()//0xc00004c088 1
    a[2]()//0xc00004c090 2
}
func F() []func() {
    b := make([]func(), 3, 3)
    for i := 0; i <3; i++ {
        j := i
        b[i] = func() {
            fmt.Println(&j, j)
        }
    }
    return b
}

Each operation only anonymous function into the array, but not executed, and the variable is referenced i, along with ichanges in the anonymous function iis also changing, so when performing these functions, they are read environment variables ilast values. The solution is to copy each variable is ithen passed to the anonymous function, so that the environment variable closure is not the same.

5.

package main

import "fmt"

func main() {
   fmt.Println(F())//2
}
func F() (r int) {
   defer func() {
      r++
   }()
   return 1
}

The output result is 2, that is, execute r=1 first, and then execute r++.

6. Recursive function

There is also a case where all closures must be used, which is a recursive function.

package main

import "fmt"

func F(i int) int {
   if i <= 1 {
      return 1
   }
   return i * F(i-1)
}

func main() {
   var i int = 3
   fmt.Println(i, F(i))//3 6
}

7, Fibonacci sequence (Fibonacci)

This sequence starts with item 3, and each item is equal to the sum of the first two items.

package main

import "fmt"

func fibonaci(i int) int {
    if i == 0 {
        return 0
    }
    if i == 1 {
        return 1
    }
    return fibonaci(i-1) + fibonaci(i-2)
}

func main() {
    var i int
    for i = 0; i <10; i++ {
        fmt.Printf("%d\n", fibonaci(i))
    }
}

summary:

Anonymous functions and closures are actually the same thing, and anonymous functions are closures. While anonymous functions bring flexibility to programming, they are also prone to bugs. Pay more attention to the parameters of the function and the issues of acceptable parameters during use.

Reference: https://cloud.tencent.com/developer/article/1706191 GO anonymous functions and closures-Cloud + Community-Tencent Cloud