函数的定义

包括以下部分:

  • 函数的声明
  • 参数
  • 返回值

函数的特点:

  • 无返回值或多返回值
  • 无默认参数
  • 不支持重载,之后的版本支持

一、函数声明

一个完整的函数声明,包含以下部分:

  • func关键字
  • 函数名
  • 参数列表
  • 返回值列表/无返回值
  • 函数体(大括号内的部分)

函数从第一条语句开始执行,碰到return或者执行完最后一条语句,函数结束

如果没有声明函数体,可能这个函数是由其他语言实现的, 比如汇编

二、参数

  • 定义的是形参,调用传的是实参,到函数里面就变成一个局部变量
  • Go都是值传递,无论是值变量还是指针地址变量,传递的是变量的拷贝副本。地址的拷贝更高效,只要复制一个地址,而复制一个比较大的对象值的话,效率低
  • 不定参数(可变长参数),如下所示
values := []int{1,2,3,4}

// ...定义的就是变长参数
func fun(a int, args ...int) {
	// 类似一个slice,可以进行for循环
	for x := range args {
		println(x)
	}
} 

// 调用函数的时候,使用...将slice转为变长参数
fun(1, values...) 


// 用interface来接受不同类型的参数
func fun2(a, int, args ...interface{}) {} 

// 但是注意,尽管 ..int和slice类型,但是变长函数和一个带有普通slice参数的函数类型不相同

func f(... int){} // 类型是: func(...int)
func g([]int) {}. // 类型是: func([]int)

三、返回值

  • 函数有多少个返回值,就要用几个参数接收
  • 通过 _ 接收不想用的参数
  • 返回值可以只定义类型,如果有定义变量,在函数体内可以直接用该变量
  • 可以显式return变量,也可以 裸返回,会返回所有定义的返回变量
func add(a,b int)(z int){
	z = a+b
	return z
}

func add(a,b int)(z int, x int){
	z = a+b
	// 此时会return所有变量,包括z和x
	return
}

四、函数签名

  • 函数的类型称为函数签名(例如 func(int, int) int
  • 如果函数有相同类型的参数,返回值,那么函数的函数签名就是一样的
package main

import "fmt"

func add(x int, y int) (z int){
	return
}
func multiply(x int, y int) (z int){
	return
}

func main() {
	fmt.Printf("%T\n", add)
	fmt.Printf("%T\n", multiply)
}


输出结果:

func(int, int) int
func(int, int) int

五、函数变量

  • 函数变量也有类型,零值为nil,可以将函数赋值给变量,也可将函数变量作为函数的返回值
package main

import "fmt"

func intPrinter(x int){
	fmt.Println(x)
}

func main() {
	var f1 func(int) int
	fmt.Println(f1 == nil)  // true

	f2 := intPrinter
	f2(100)  // 100

	fmt.Printf("%T\n", f2) // func(int)
}