函数

作者: ffacs 分类: Golang 发布时间: 2020-03-10 09:03

Go中没有函数重载!

函数定义

func name(arg1 type,arg2 type...) return_type{

}

命名返回值

package main

import "fmt"

func add_all(arr []int) (sum int) {
    for _, v := range arr {
        sum += v
    }
    return
}

func main() {
    a := [...]int{1, 2, 3, 4, 5}
    fmt.Println(add_all(a[:]))
}

多返回值

package main

import "fmt"

func add_all(arr []int) (indexsum, sum int) {
    for i, v := range arr {
        indexsum += i
        sum += v
    }
    return
}
func main() {
    a := [...]int{1, 2, 3, 4, 5}
    fmt.Println(add_all(a[:]))// 10 15
}

变长参数

package main

import "fmt"

func add_all(cnt int, arr ...int) (sum int) { //变长参数只能放在最后面
    for i := 0; i < cnt; i++ {
        sum += arr[i]
    }
    return
}
func main() {
    fmt.Println(add_all(3, 1, 2, 3))
}

闭包函数

匿名函数

go中函数也是一个类型,可以达到在函数中定义函数的效果。

package main

import "fmt"

func main() {
    var x int = 1
    var fun = func(a int) (ans int) {
        x = 2
        ans = a * a
        return
    }
    fmt.Println(fun(2), x)
}
package main

import "fmt"

func f(i int) func() int {
    return func() int {
        i++
        return i
    }
}

func main() {
    var c = func(a, b int) (sum int) {
        sum = a + b
        return
    }(1, 2)
    fmt.Println(c)//3
}

闭包

package main

import "fmt"

func f(i int) func() int {
    return func() int {
        i++
        return i
    }
}

func main() {
    var c = f(0)
    fmt.Println(c(), c())//1,2
}

上面的例子中,i这个变量escape了,到了heap 中,所以每次调用的都是同一个i,

其实返回的不只有这个函数,还返回了函数外层的变量引用,实际上是返回了一个结构体,里面有函数和变量的地址。当调用函数的时候就是在调用这个匿名函数

识别出变量需要在堆上分配,是由编译器的一种叫escape analyze的技术实现的。如果输入命令:

go build --gcflags=-m main.go
package main

import "fmt"

func f(i int) func() int {
    return func() int {
        i++
        return i
    }
}

func main() {
    var c = f(0)
    var d = f(0)
    fmt.Println(c(), d())// 1 1
}

cd处在两个不同的环境,所以不会影响别人的i。返回闭包时并不是单纯返回一个函数,而是返回了一个结构体,记录下函数返回地址和引用的环境中的变量地址。

看这里

异常处理

defer

defer关键字会将函数压入栈中,等到外层函数退出即将时再从栈中取出运行

package main

import "fmt"

func main() {
    defer fmt.Print("B")
    fmt.Println("A")
}// A B

发表评论

电子邮件地址不会被公开。 必填项已用*标注