头图

Hello everyone, today I will sort out the usage of Go language functions and share them with you. Please advise, thank you.

This "Go Language Function Usage" is divided into three chapters, and this article is the second chapter.

Contents of this chapter

  • anonymous function
  • Closure
  • recursive function
  • defer call

anonymous function

introduce

In the Go language, functions can be passed or used like ordinary variables, and anonymous functions can be defined in the code at any time.

An anonymous function consists of a function declaration without a function name and a function body. The advantage of anonymous functions is that the variables in the function can be used directly without declaration.

Anonymous functions have the feature of dynamic creation, which enables anonymous functions to directly reference external variables without passing parameters.

use

The first usage: assign an anonymous function to a variable, and call the anonymous function through the variable

 sum := func(a, b int) int {
  return a + b
}
fmt.Println(sum(1, 2)) // 输出 3

The second usage: use it directly when defining an anonymous function, this method can only be used to pass parameters once

 sum := func(a, b int) int {
    return a + b
}(1,2) // 传入参数
fmt.Println(sum) // 输出 3

The third usage: assign an anonymous function to a global variable, and the anonymous function can be used in the current program

 package main

import "fmt"

var (
  // 全局变量必须首字母大写
    Sum = func(a, b int) int {
        return a + b
    }
)

func main() {
    sum := Sum(1, 2)
    fmt.Println("sum=", sum) // 输出 sum= 3
}

Closure

introduce

A "closure" is an expression (usually a function) that has many variables and an environment to which those variables are bound, so that these variables are also part of the expression.

Closures are functions that reference free variables. The referenced free variable will exist with the function, even if it has left the environment in which it was created. So, there is another way of saying that a closure is an entity composed of a function and its associated reference environment. Closures can have multiple instances at runtime, and different reference environments and the same function composition can produce different instances.

It can be understood as: a closure is a combination of an anonymous function and the environment referenced by the anonymous function, similar to that of a regular function referring to a global variable in the environment of a package.

Advantages of closures

  • Variables can be resident in memory
  • Variables do not pollute the global
The local variables returned by the scope in the closure will not be destroyed and reclaimed immediately, which may occupy more memory and overuse the closure will lead to performance degradation.

use

 package main

import "fmt"

func main() {
    n := 0
    count := func() int {  // 这就是一个闭包
        n += 1
        return n
    }
    fmt.Println(count()) // 输出 1
    fmt.Println(count()) // 输出 2
}

Regular functions, anonymous functions + global variables + packages are equivalent to closures, count not only store the return value of the function, but also store the state of the closure.

When the closure is returned and assigned to a variable of the same type, the state of the entire closure is assigned at the same time, and the state will always exist in the externally assigned variable count , until count is Destruction, the entire closure life cycle ends.

It can also be written in the following form

 package main

import "fmt"

func Count() func() int { // 返回函数
    n := 0
    return func() int {
        n++
        return n
    }
}

func main() {
    count := Count()
    fmt.Println(count()) // 输出 1
    fmt.Println(count()) // 输出 2
}
Advanced closure features, such as closures in concurrency. It will be introduced in later chapters.

recursive function

introduce

Recursion is calling itself during the running process.

A function that calls itself is called a recursive function.

Condition for recursion:

  1. The subproblem needs to be the same thing as the original problem, but simpler.
  2. It cannot call itself indefinitely, there must be an exit, which is simplified to non-recursive state processing.

use

Example: Number factorial

The factorial of a positive integer is the product of all positive integers less than and equal to that number, and the factorial of 0 is 1.

 package main

import "fmt"

func factorial(i int) int {  // 解读为 5*4*3*2*1=120 
    if i <= 1 {
        return 1
    }
    return i * factorial(i-1)
}

func main() {
    var i int = 5
    fmt.Printf("%d\n", factorial((i))) // 120
}
In 1808, Christian Carman introduced this notation.

Example: Fibonacci sequence

The sequence starts at term 3, and each term is equal to the sum of the previous two.

 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 ", fibonaci(i)) // 0 1 1 2 3 5 8 13 21 34
    }
}

defer call

introduce

The use of defer delayed calls has been introduced in the basic grammar. Today, we will take a deep dive into using the defer mechanism.

defer feature

  1. The keyword defer is used to register defer calls.
  2. These calls are not executed until return. Therefore, it can be used for resource cleanup.
  3. Multiple defer statements are executed in a first-in, last-out manner.
  4. The variables in the defer statement are determined when the defer statement is made.
  5. An error occurs in one of the deferred calls, these calls will still be executed.
When the statement following defer is executed, the parameters of the function call will be saved, but not executed. That is, a copy.

defer use

  1. close file handle
  2. lock resource release
  3. database connection release

use

Multiple defer registrations are executed in FILO order (first in, last out) principle.

 package main

func main() {
    defer println("1") // 先进来, 最后出去
    defer println("2")
    defer println("3") // 最后进来, 先出去
}

output

 3
2
1

Lazy call parameters are evaluated or copied at registration time, and can be read "lazy" with pointers or closures.

 package main

import "fmt"

func main() {
    x, y := 10, 100
    defer func(i int) {
        fmt.Printf("defer x = %v, y = %v\n", i, y) // y 闭包引用
    }(x) // x 被复制

    x += 10
    y += 20
    println("x = ", x, "y = ", y)
}

output

 x =  20 y =  120
defer x = 10, y = 120

The order of execution of both defer and return

  1. Named return value (function return value is named return value)
 package main

import "fmt"

func foo() (i int) { // 3.return i 值
    i = 0
    defer func() {
    fmt.Println(i) // 2.读取临时变量地址(返回值)
    }()
    return 2 // 1.返回值赋值,写入临时变量
}

func main() {
    foo()
}

output

 2

In the foo() function that returns a value (here the return value is i), when return 2 is executed, the value of i has actually been reassigned to 2. So the output of defer closure is 2.

Parse:

The mechanism of return: 1. First put the return value into a temporary variable (assign the return value) 2. Then return the return value to the callee.

The defer function is executed between the two operations of return.

The execution order is: first assign the return value, that is, put the return value in a temporary variable, then execute defer, and then return to the place where the function was called.

b0wWvD.png

  1. Unnamed return value (that is, the function return value is an unnamed function return value)
 package main

import "fmt"

func foo() int {
    var i int
    defer func() {
        i++ // 这个地方 i,不是临时变量
        fmt.Println("defer = ", i) // 输出 defer = 1
    }()
    return i // 返回值赋值,写入临时变量
}

func main() {
    fmt.Println("return = ", foo()) // 输出 return = 0
}

Parse:

return first puts the return value in a temporary variable. The defer function cannot obtain the address of this temporary variable (there is no function return value), so no matter what the defer function does, it will not cause any changes to the final return value.

Technical articles are continuously updated, please pay more attention~~

Search WeChat public account【The Gunslinger of Maoer Mountain】, follow me


帽儿山的枪手
71 声望18 粉丝