zoukankan      html  css  js  c++  java
  • Go 函数 #3

    ◆【函数】

    1,定义函数使用func关键字,具体格式如下:

    func 函数名(参数)(返回值){

    函数体

    }

    例:

    func sum(x int, y int) (ret int){ #声明参数x,y和返回值ret.

    ret = x + y

    return

    }

    2,可变参数

    可变参数是指函数的参数数量不固定。在参数名后加...来标识。

    可变参数在函数体中是切片类型,通常作为函数的最后一个参数。

    例:

    func intSum(x ...int) int {

        fmt.Println(x)

        sum := 0

        for _, v := range x {

            sum = sum + v

        }

        return sum

    }

    3,多返回值

    Go语言中函数支持多返回值,函数如果有多个返回值时必须用()将所有返回值扩起来。

    例:

    func calc(x, y int) (int, int) {

        sum := x + y

        sub := x - y

        return sum, sub

    }

    函数定义时可以给返回值命名,并在函数体中直接使用这些变量,最后通过return关键字返回。

    func calc(x, y int) (sum, sub int) {

        sum = x + y

        sub = x - y

        return

    }

    4,返回值补充

     

    当一个函数返回值类型为slice时,nil可以看做是一个有效的slice,没必要显示返回一个长度为0的切片。

    func someFunc(x string) []int {

        if x == "" {

            return nil // 没必要返回[]int{}

        }

        ...

    }

    5,内置函数    介绍

    close    主要用来关闭channel。

    len        用来求长度,比如string、array、slice、map、channel。

    new        用来分配内存,主要用来分配值类型,比如int、struct。返回的是指针。

    make    用来分配内存,主要用来分配引用类型,比如chan、map、slice。

    append    用来追加元素到数组、slice中。

    panic和recover    用来做错误处理。

     

     

    ◆【匿名函数】

    func(参数)(返回值){

    函数体

    }

    匿名函数因为没有函数名,所以没办法像普通函数那样调用,所以匿名函数需要保存到某个变量或者作为立即执行函数.

    ①匿名函数保存到变量,通过变量调用匿名函数。

        add := func(x, y int) {

            fmt.Println(x + y)

        }

        add(1, 2)

     

    ②自执行函数:匿名函数定义完加()直接执行。

        func(x, y int) {

            fmt.Println(x + y)

        }(1, 2)

     

    ◆【闭包】

    闭包是一个函数和环境的组合。

    ①定义一个函数,它的返回值是一个函数。

    判断一个函数是否是闭包,就看它有无引用函数外部的变量。

    //函数名为test;返回值为func(),即函数。

    func test() func() {

    return func() { //返回值为匿名函数。

    函数体

    }

    }

     

    func add() func(int) int {

        var x int

        return func(y int) int {

            x += y

            return x

        }

    }

     

    func main() {

        var f = add()

        fmt.Println(f(10)) //10

        fmt.Println(f(20)) //30

        fmt.Println(f(30)) //60

     

        f1 := add()

        fmt.Println(f1(40)) //40

        fmt.Println(f1(50)) //90

    }

    ※变量f就是一个闭包。 在f的生命周期内,变量x也一直有效。

     

    ◆【defer语句】

    ①在defer归属的函数即将返回时,将延迟处理的语句按defer定义的逆序进行执行,也就是说,先被defer的语句最后被执行,最后被defer的语句,最先被执行。

    例:

    func main() {

        fmt.Println("start")

        defer fmt.Println(1)

        defer fmt.Println(2)

        defer fmt.Println(3)

        fmt.Println("end")

    }

    结果:3,2,1

    ※由于defer语句延迟调用的特性,所以defer语句能非常方便的处理资源释放问题。比如:资源清理、文件关闭、解锁及记录时间等。

     

    ②defer执行时机

    在Go语言的函数中return语句在底层并不是原子操作,它分为给返回值赋值和RET指令两步。而defer语句执行的时机就在返回值赋值操作后,RET指令执行前。

     

    ③panic/recover

    panic可以在任何地方引发,但recover只有在defer调用的函数中有效。

    例:

    func funcA() {

        fmt.Println("func A")

    }

     

    func funcB() {

        defer func() {

            err := recover()

            //如果程序出出现了panic错误,可以通过recover恢复过来

            if err != nil {

                fmt.Println("recover in B")

            }

        }()

        panic("panic in B")

    }

     

    func funcC() {

        fmt.Println("func C")

    }

    func main() {

        funcA()

        funcB()

        funcC()

    }

    1,recover()必须搭配defer使用。

    2,defer一定要在可能引发panic的语句之前定义。

  • 相关阅读:
    MVVM模式和在WPF中的实现(一)MVVM模式简介
    C#中实现并发的几种方法的性能测试
    搞笑:儿子的日记,叔叔妈妈
    MSN头像中小黄鸭子是什么?
    某人分析的70后,80后,90后
    有趣的纹身
    百度首页人物logo第一期:许三多
    关于微软Windows未来的一点畅想
    我把最难的21个汉字写进一篇文章
    百度还可以这样玩!
  • 原文地址:https://www.cnblogs.com/mountain2011/p/12494844.html
Copyright © 2011-2022 走看看