函数

golang的函数有很多独特的创新。比如golang的函数支持多个返回值,而且支持返回值命名,golang的函数中支持defer

go函数声明格式

func 函数名(参数列表) (返回值列表) {
    //函数体
}

在参数列表中,多个相同类型可简写如下


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

//参数列表可简写
func add2(a,b int) int {
    return a+b
}

golang支持函数有多个返回值。如果函数只有一个返回值可以简写成如下格式

func 函数名(参数列表) 返回值 {
    //函数体
}

golang还支持命名的返回值。

func read(url string) (string,error) {
    content, err := 函数类型的零值是nil。调用值为nil的函数值会引起pani
    return string(content),nil
}

//只返回一个返回值
func add(a int,b int) int {
    return a+b
}

//无返回值
func swap(a *int,b *int) {
    temp := *a
    *a = *b
    *b = temp
}

//命名的返回值
func add(a int,b int)(c int) {
    c = a+b
    return
}

函数类型

在golang中定义的函数可以被看做一种值类型,可以赋值给函数类型变量。函数类型的默认初始值为nil。

func add(a int,b int) int {
    return a+b
}
fn := add       //fn的类型为 func(a,b int)
fmt.Println(f(1,2))

可变参数

golang支持可变参数,但是要求参数类型是一致的。其实golang的可变参数是一个slice

可变参数在fmt包中非常常见。比如Printf定义为func Printf(format string, a ...interface{}) (n int, err error) 。 由于使用了interface{}接口类型,所以它可以接收任意类型参数。

func sum(arr ...int) int {
    totalNum := 0
    for _, v := range arr {
        totalNum += v
    }
    return totalNum
}

defer

golang中defer关键字运行我们推迟到函数返回之前执行代码块或函数。defer通常被设计来关闭资源或者处理panic。一个函数中支持有多个defer, 多个defer的执行顺序为代码位置逆序。

func ReadFile(filename string) ([]byte, error) {
    f, err := os.Open(filename)
    if err != nil {
        return nil, err
    }
    defer f.Close()
    return ReadAll(f)
}

匿名函数

golang还支持匿名函数,匿名函数经常在defergo关键字后面看到。

func ReadFile(filename string) ([]byte, error) {
    f, err := os.Open(filename)
    if err != nil {
        return nil, err
    }
    defer func() { //匿名函数
        f.Close()
        //再做点其他事情
    }()
    return ReadAll(f)
}


go func(){ //开启一个go协程
    //做点事情
}()

函数递归

golang的函数也支持递归,如下我们用递归的方式实现斐波那契数列。

func fibonacci(n int) (res int) {
    if n <= 1 {
        res = 1
    } else {
        res = fibonacci(n-1) + fibonacci(n-2)
    }
    return
}