函数

假设 f1 需要 3 个参数 f1(a, b, c int) ,同时 f2 返回 3 个参数f2(a, b int) (int, int, int) ,就可以这样调用 f1: f1(f2(a, b))

Go 语言不支持函数重载 函数重载(function overloading)指的是可以编写多个同名函数,只要它们拥有不同的形参与/或者不同的返回值,在 Go 里面函数重载是不被允许的。 这将导致一个编译错误:

函数也可以以申明的方式被使用,作为一个函数类型,就像:

type binOp func(int, int) int

6.2.4 改变外部变量

指针传递

6.3 传递变长参数

6.4 defer

关键字 defer 允许我们推迟到函数返回之前(或任意位置执行 return 语句之后)一刻才执行某个语句或函数,因为 return 语句同样可以包含一些操作,而不是单纯地返回某个值

注:可以用来记录程序开始和结束时间

func Function1() {
	fmt.Printf("In Function1 at the top\n")

	defer Function2() // 加不加这个关键字是有很大区别的
	//Function2()

	i := 0
	defer fmt.Println(i)
	i++

	fmt.Printf("In Function1 at the bottom!\n")
	return
}

func Function2() {
	fmt.Printf("函数2:延迟到调用函数结束!\n")
}

当有多个 defer 行为被注册时,它们会以逆序执行(类似栈,即后进先出):下面代码会输出 4 3 2 1 0

func f() {
	for i := 0; i < 5; i++ {
		defer fmt.Printf("%d ", i)
	}
}

6.6 递归函数

在使用递归函数时经常会遇到的一个重要问题就是栈溢出:一般出现在大量的递归调用导致的程序栈内存分配耗尽。 这个问题可以通过一个名为懒惰求值的技术解决,在 Go 语言中,我们可以使用管道(channel)和 goroutine(详见第 14.8 节)来实现

可以相互调用,行程闭环

package main

import "fmt"

func main() {
	for i := 0; i < 10; i++ {
		fmt.Printf("%d is even: is %t\n", i, even(i))
		fmt.Printf("%d is odd: is %t\n", i, odd(i))
	}
}

func even(nr int) bool {
	if nr == 0 {
		return true
	}
	return odd(RevSign(nr) - 1)
}

func odd(nr int) bool {
	if nr == 0 {
		return false
	}
	return even(RevSign(nr) - 1)
}

func RevSign(nr int) int {
	if nr < 0 {
		return -nr
	}
	return nr
}