golang学习笔记(五)函数

2022-11-13  本文已影响0人  NIIIICO
1、书写方式
package main

import "fmt"

func main() {
    test1()          // 1、无参
    test2_1(1, 2)    // 2、有参
    test2_2(1, 2, 3) // 不定参 test2_2()

    // 3、无参,单个返回值
    fmt.Println("test3_1:", test3_1())
    fmt.Println("test3_2:", test3_2())
    fmt.Println("test3_3:", test3_3())

    // 4、无参,多个返回值
    a, b := test4_1()
    fmt.Println("test4_1:", a, b)
    a, b = test4_2()
    fmt.Println("test4_2:", a, b)
    a, b = test4_3()
    fmt.Println("test4_3:", a, b)

    // 5、有参,有返回值
    max, min := test5(1, 2)
    fmt.Println("test5:", max, min)
}

// 1、无参无返回值
func test1() {
    fmt.Println("我是test1函数")
}

// 2.1、有参无返回值
func test2_1(a int, b int) {
    fmt.Printf("我是test2_1函数:a=%d ,  b=%d\n", a, b)
}

// 2.2、不定参数,只能放在最后一个参数,不定参数可以不传
func test2_2(a ...int) {
    for i, value := range a {
        fmt.Printf("我是test2_2函数a[%d]=%d\n", i, value)
    }
    // 全部元素传递
    // test2_3(a...)
    // 传递部分元素,下标0-1的元素传递给下一个函数,含前不含后
    // test2_3(a[:1]...)
    // 传递部分元素,下标1-结束的元素传递给下一个函数
    // test2_3(a[1:]...)
    // 传递部分元素,下标1-2的元素传递给下一个函数,含前不含后
    test2_3(a[1:2]...)
}

func test2_3(a ...int) {
    for i, value := range a {
        fmt.Printf("我是test2_3函数a[%d]=%d\n", i, value)
    }
}

// 3.1、无参,只有一个返回值
func test3_1() int {
    return 1
}

// 3.2、无参,只有一个返回值
func test3_2() (result int) {
    return 1
}

// 3.3、无参,只有一个返回值
func test3_3() (result int) {
    result = 1
    fmt.Println("in test3_3")
    return
}

// 4.1、无参,多个返回值
func test4_1() (int, int) {
    return 1, 2
}

// 4.2、无参,多个返回值
func test4_2() (a int, b int) {
    return 3, 4
}

// 4.3、无参,多个返回值
func test4_3() (a int, b int) {
    a, b = 5, 6
    fmt.Println("test4_3")
    return
}

// 5、有参有返回值
func test5(a, b int) (max, min int) {
    if a > b {
        max = a
        min = b
    } else {
        max = b
        min = a
    }
    return
}
2、函数类型

函数类型也是一种数据类型,通过type起名

package main

import "fmt"

// 函数类型也是一种数据类型,通过type起名
type FuncType func(int, int) int

func main() {
    // 声明一个函数类型的变量
    var funcTest FuncType
    // 给变量赋值
    funcTest = add
    fmt.Println("funcTest:", funcTest(1, 2))

    // 重新赋值
    funcTest = minus
    fmt.Println("funcTest:", funcTest(1, 2))
}

func add(a, b int) int {
    return a + b
}

func minus(a, b int) int {
    return a - b
}
3、回调函数

回调函数:函数的参数是函数类型

package main

import "fmt"

// 函数类型也是一种数据类型,通过type起名
type FuncType func(int, int) int

func main() {
    fmt.Println("calc的结果是:", calc(1, 2, minus))
}

// 回调函数,函数的参数是函数类型
func calc(a, b int, fTest FuncType) int {
    return fTest(a, b)
}

func add(a, b int) int {
    return a + b
}

func minus(a, b int) int {
    return a - b
}
4、匿名函数

(1)匿名函数,没有函数名字
(2)后边跟()表示调用此匿名函数

package main

import "fmt"

func main() {
    age := 18
    name := "LiMing"

    // 匿名函数,没有函数名字
    f := func() {
        fmt.Printf("匿名函数 name:%s, age:%d\n", name, age)
    }
    f()

    // 后边的圆括号表示调用此匿名函数
    func() {
        fmt.Println("匿名函数")
    }()

    max, min := func(i, j int) (max, min int) {
        if i > j {
            max = i
            min = j
        } else {
            max = j
            min = i
        }
        return
    }(10, 20)
    fmt.Printf("max=%d, min=%d", max, min)
}
5、闭包

(1)闭包以引用方式捕获外部参数
(2)闭包不关心 捕获的变量 是否已经超出作用域,只要闭包还在使用它,这些变量就会存在

package main

import "fmt"

func main() {
    age := 18
    name := "LiMing"

    // 闭包以引用方式捕获外部参数
    func() {
        fmt.Printf("匿名函数,初始值 name:%s, age:%d\n", name, age)
        age = 19
        name = "LiDaMing"
        fmt.Printf("匿名函数,修改后的值 name:%s, age:%d\n", name, age)
    }()

    fmt.Printf(" name:%s, age:%d\n", name, age)

    // 结果是 1,1,1
    fmt.Println("test 结果:", test())
    fmt.Println("test 结果:", test())
    fmt.Println("test 结果:", test())

    // 结果是 1,2,3
    f := test2()
    fmt.Println("test 结果:", f())
    fmt.Println("test 结果:", f())
    fmt.Println("test 结果:", f())
}

func test() int {
    var x int
    x++
    return x
}

func test2() func() int {
    var x int

    // 闭包不关心 捕获 的变量是否已经超出作用域,只要闭包还在使用它,这些变量就会存在
    return func() int {
        x++
        return x
    }
}
6、defer

(1)延时,在函数结束前调用
(2)多个defer,后进先出 LIFO
(3)多个defer,如果某个函数发生错误,也可以都执行到
(4)崩溃代码不用defer修饰,后边的defer就不会执行

package main

import (
    "fmt"
)

func main() {
    // 延时,函数结束前调用
    // 后进先出 LIFO

    // 如果某个函数发生错误,也可以都执行到
    // hello world !!!
    // panic: runtime error: integer divide by zero
    defer fmt.Print("!!! \n")
    defer fmt.Print("world ")
    defer test(0)
    defer fmt.Print("hello ")

    // world2 !!!2
    defer fmt.Print("!!!2 \n")
    defer fmt.Print("world2 ")
    // 崩溃代码不用defer修饰,后边的defer就不会执行
    test(0)
    defer fmt.Print("hello2 ")
}

func test(a int) int {
    return 100 / a
}
7、defer结合匿名函数

(1)不需要传参的函数,使用defer后,因为是后执行,捕获的是修改后的参数
(2)需要传参的函数,使用defer后,调用的时候已经传了值,只是延后调用

package main

import (
    "fmt"
)

func main() {
    // main a =  111  b =  222
    // defer a =  111  b =  222
    test()

    // main a =  111  b =  222
    // defer a =  10  b =  20
    test1()
}

func test() {
    a, b := 10, 20

    defer func() {
        fmt.Println("defer a = ", a, " b = ", b)
    }()

    a, b = 111, 222
    fmt.Println("main a = ", a, " b = ", b)
}

func test1() {
    a, b := 10, 20

    defer func(a, b int) {
        fmt.Println("defer a = ", a, " b = ", b)
    }(a, b)

    a, b = 111, 222
    fmt.Println("main a = ", a, " b = ", b)
}

8、命令行参数

通过 os.Args 接收用户命令行传递的参数,以字符串传递

package main

import (
    "fmt"
    "os"
)

// 输出结果:
// length =  2
// value =  C:\Users\zhaolin\AppData\Local\Temp\go-build1874253334\b001\exe\10.exe
// value =  a
func main() {
    // 通过 os.Args 接收用户命令行传递的参数,以字符串传递
    list := os.Args
    l := len(list)

    fmt.Println("length = ", l)

    for _, value := range list {
        fmt.Println("value = ", value)
    }
}
上一篇 下一篇

猜你喜欢

热点阅读