函数的定义
包括以下部分:
- 函数的声明
- 参数
- 返回值
函数的特点:
- 无返回值或多返回值
- 无默认参数
- 不支持重载,之后的版本支持
一、函数声明
一个完整的函数声明,包含以下部分:
- 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)
}