Go语言中函数参数传递采用的是值传递的方式。所谓“值传递”,就是将实际参数在内存 中的表示逐位拷贝到形式参数中。对于像整型、数组、结构体这类类 型,它们的内存表示就是它们自身的数据内容,因此当这些类型作为实参类型时,值传递 拷贝的就是它们自身,传递的开销也与它们自身的大小成正比。
但是像 string、切片、map 这些类型就不是了,它们的内存表示对应的是它们数据内容 的“描述符”。当这些类型作为实参类型时,值传递拷贝的也是它们数据内容的“描述 符”,不包括数据内容本身,所以这些类型传递的开销是固定的,与数据内容大小无关。 这种只拷贝“描述符”,不拷贝实际数据内容的拷贝过程,也被称为“浅拷贝”。
函数声明
func 函数名(参数) (返回值){
函数体
}
函数声明示例
// 当形参参数类型相同时,可以只保留最后一个元素类型,前面的类型都可以省略
func add(n1, n2 int) int {
return n1 + n2
}
func main() {
fmt.Println(add(1, 1)) // 2
}
函数的变长参数
func add(n1, n2 int, args ...int) int {
for _, v := range args {
fmt.Println(v)
}
return n1 + n2
}
func main() {
n := []int{6, 7, 8}
fmt.Println(add(1, 1, n...)) // 6 7 8 2
}
函数的多返回值
func add(n1, n2 int) (int, int) {
r1 := n1 + n2
r2 := n1 * n2
return r1, r2
}
func main() {
fmt.Println(add(1, 1)) // 2 1
}
匿名函数
匿名函数就是没有函数名的函数,当我们不希望给函数起名字的时候,可以使用匿名函数,匿名函数不能够独立存在,它可以被赋值于某个变量或直接对匿名函数进行调用。
// 将匿名函数保存到变量
a := func() {
fmt.Println("test1")
}
a() // 调用
// 直接对匿名函数进行调用,最后的一对括号表示对该匿名函数的直接调用执行
func() {
fmt.Println("test2")
}() // 调用
延迟函数
defer关键字 + 函数调用来实现延迟函数
延迟函数在函数return之后退出之前执行,仅在函数退出之前执行,for循环内或其它啥的用这个不起作用
func test(n1, n2 int) string {
// 延迟执行:return调用以后,在函数退出之前执行。注意:仅仅在函数退出之前执行,for循环内或其他啥的用这个是不起作用的
// 延迟函数多用于打开文件、延迟关闭、处理(处理出现错误)
defer func() {
fmt.Println("defer")
}()
fmt.Println("befor")
fmt.Println(n1 / n2)
fmt.Println("end")
return ""
}
func main() {
test(1, 1) // befor 1 end defer
test(1, 0) // 手动来一个除零异常, 那么得到的结果为: befor defer 然后是异常信息
}