Go basic functions, anonymous functions, defer, panic/recover

Function A
function is an organized, reusable, code block used to perform and specify tasks.
Go language expenditures, functions, anonymous functions and closures

package main

import (
    "fmt"
"strings"
)
func main() {
    
    
    // 定义函数的格式
    // func 函数名(参数)(返回值){
    
    
    // }
    //通过函数名就可以调用函数,函数有参数的情况下,
    // 必须填写参数,调用函数的结果,就是返回值
    fmt.Println("fu1函数", fu1(3, 2))
    //可变参数的函数调用,除了第一个参数,其他的参数都算作是,第二个参数的
    fmt.Println("fu2函数", fu2(1, 2, 3, 4, 5, 6))
    //多个返回值
    o, p := fu3()
    fmt.Println(o, p)
    l, n := fu4()
    fmt.Println(l, n)
    //函数作为函数的参数和返回值
    ff := fu5(fu6)
    //ff是fu5的返回值,是一个func(x int)int类型的函数
    fmt.Println(ff(1))
    testAdd()
    testMakeSuffixFunc()
    testCalc()
}
// 定义一个函数,返回参数一加上参数二
// 函数参数中,相邻的两个参数的类型相同可以简写,如下:
func fu1(i, o int) (x int) {
    
    
    x = i + o
    return
}
// 可变参数的函数,如下函数中,参数o是一个可变长度的参数,
// o的类型是一个切片,可变长度的参数,只能写在所有参数中的最后一个
func fu2(i int, o ...int) (x int) {
    
    
    for _, v := range o {
    
    
        i += v
    }
    x = i
    return
}
//多返回值
//返回值,没有命名变量只写了类型,那么rutern后面就行跟上变量
func fu3() (int, int) {
    
    
    return 2, 3
}
//返回命名的变量
//返回值中,命名了变量,那么return后面就不用写变量
//在参数,和返回值中命名好的变量可以直接使用,不用再命名了
func fu4() (x, y int) {
    
    
    x = 3
    y = 3
    return
}
// 函数还可以作为函数的返回值和变量
func fu5(f func(int, int) int) (f1 func(int) int) {
    
    
    a, p := 1, 2
    o := f(a, p)
    fmt.Println(o)
    //定义了一个匿名函数
    f1 = func(i int) int {
    
    
        return i
    }
    return
}
func fu6(o, p int) int {
    
    
    return o * p
}
//闭包
//闭包指的是一个函数,引用了他外部的数据
//案例一
func adder(x int) func(i int) int {
    
    
    x += x
    return func(i int) int {
    
    
        x += i
        return x
    }
}
//变量adder是一个函数并且他引用了其外部作用域中的x变量,此时adder就是一个闭包
//在adder变量的生命周期内,x一直有效
func testAdd() {
    
    
    adder := adder(5)
    fmt.Println("闭包案例一")
    fmt.Println(adder(2))
    fmt.Println(adder(3))
    fmt.Println(adder(4))
}
//闭包
//案例二
func makeSuffixFunc(i string) func(s string) string {
    
    
    return func(s string) string {
    
    
        if strings.HasSuffix(s, i) {
    
    
            return s
        }
        s += i
        return s
    }
}
//调用两次makeSuffixFunc函数,返回两个函数,两个函数之间不会互相冲突
func testMakeSuffixFunc() {
    
    
    fmt.Println("闭包案例二")
    suffix1 := makeSuffixFunc(".txt")
    fmt.Println(suffix1("fdsfsdf"))
    suffix2 := makeSuffixFunc(".JPG")
    fmt.Println(suffix2("fdsfsdf"))
}
//闭包
//案例三
func calc(i int) (func(int) int, func(int) int) {
    
    
    add := func(x int) int {
    
    
        i += x
        return i
    }
    sub := func(x int) int {
    
    
        i -= x
        return i
    }
    return add, sub
}
//因为变量add和sub,一直在操作同一个变量i,所以只要add和sub一直被调用,
// 那么i一直存在并且会将i以类似缓存的方式保存起来
func testCalc() {
    
    
    fmt.Println("闭包案例三")
    add, sub := calc(10)
    fmt.Println(add(1), sub(2))
    fmt.Println(add(3), sub(4))
    fmt.Println(add(5), sub(6))
}

Defer statement The defer statement in the
Go language will delay the execution of the following statement. The function that defer belongs to will return the value, and the defer statement
will be executed in the reverse order of the defer statement definition. The statement of defer is executed first, and the statement of defer is executed later. When to execute the defer statement first .
In the Go language, the bottom layer of return is not an atomic operation. It is divided into return value assignment and the actual execution of the return command. Defer is after the return value assignment and before the return

package main

import "fmt"
func main() {
    
    
    fmt.Println(def1())
    fmt.Println(def2())
    fmt.Println(def3())
    fmt.Println(def4())
    def5()
}
//defer后的函数必须被调用
//return一共三步
// 1.把x值赋给返回值
// 2.defer语句中给x+1,并没有给返回值加一
// 3.执行retuen命令
func def1() int {
    
    
    x := 5
    defer func() {
    
    
        x++
    }()
    return x
}
//return一共三步
// 1.把5值赋给返回值x
// 2.defer语句中给x+1,此时x就是返回值,所以此时x就是6
// 3.执行retuen命令
func def2() (x int) {
    
    
    defer func() {
    
    
        x++
    }()
    return 5
}
//return一共三步
// 1.把x值赋给返回值y
// 2.defer语句中给x+1,此时y是返回值,所以y等于5
// 3.执行retuen命令
func def3() (y int) {
    
    
    x := 5
    defer func() {
    
    
        x++
    }()
    return x
}
//return一共三步
// 1.把5值赋给返回值x
// 2.defer语句中给x+1,此时x是匿名函数中的x,不会影响到def4中的x,所以返回值为5
// 3.执行retuen命令
func def4() (x int) {
    
    
    defer func(x int) {
    
    
        x++
    }(x)
    return 5
}
//面试题
func calc(index string, a, b int) int {
    
    
    ret := a + b
    fmt.Println(index, a, b, ret)
    return ret
}
func def5() {
    
    
    x := 1
    y := 2
    //defer执行之前会确认函数中所有的参数,再进行压栈,之后参数的改动,不影响defer后的函数
    defer calc("AA", x, calc("A", x, y)) //calc("AA",1,3)
    x = 10
    defer calc("BB", x, calc("B", x, y)) //calc("BB",10,12)
    y = 20
}


There is currently no exception mechanism in panic/recover Go language, but the panic/recover mode is used to handle exceptions. Panic can be triggered anywhere, but recover can only be used in functions called by defer.

package main

import "fmt"
func main() {
    
    
    f1()
    f2()
    f3()
}
func f1() {
    
    
    fmt.Println("a")
}
//defer语句会在panic抛异常之前运行
func f2() {
    
    
    fmt.Println("b")
    defer func() {
    
    
        //程序没有终止,被重新启动了
        recover()
    }()
    panic("Error")
}
func f3() {
    
    
    fmt.Println("c")
}

Guess you like

Origin blog.csdn.net/weixin_44865158/article/details/114640986