什么是函数
func main() {fmt.Println("hello,world")//调用函数fmt.Println(add(1, 2))
}// func 函数名(参数,参数。。。),函数调用返回值类型()
func add(a, b int) int {c := a + breturn c
}
函数的声明与调用
func main() {//函数的调用printinfo()myprint("zhounan")myprint2(add2(1, 2))x, y := swap("zhounan", "daawei")fmt.Println(x, y)}// 无参无返回值
func printinfo() {fmt.Println("printinfo")
}// 一个有参的函数
func myprint(msg string) {fmt.Println(msg)
}
func myprint2(msg int) {fmt.Println(msg)
}// 两个有参的函数
func add2(a, b int) int {c := a + breturn c
}// 有多个返回值
func swap(x, y string) (string, string) {return y, x
}
形式参数和实际参数
func main() {a := max(90, 100)fmt.Println(a)
}// max 两个数字比大小
// 形式参数 num1,num2
// 实际参数 你输入的两个值
func max(num1, num2 int) int {var result intif num1 > num2 {result = num1} else {result = num2}return result
}
可变参数
// 可变参数
func main() {getSun(1, 2)}
func getSun(nums ...int) {sum := 0for i := 0; i < len(nums); i++ {fmt.Println(nums[i])sum = sum + nums[i]}fmt.Println("sum:", sum)}
值传递
func main() {//值传递//定义数组 [个数]类型{初始化}//修改arr2并不会影响arr1//值传递 传递的是数据的副本,修改数据,对于原始的数据没有影响//值传递的类型,默认是值传递,基础类型,array,structarr := [4]int{1, 2, 3, 4}//传递:传递arrfmt.Println(arr)update(arr)}
func update(arr2 [4]int) {fmt.Println("arr2接收的数据", arr2)arr2[0] = 100fmt.Println("arr2修改后的数据", arr2)
}
引用传递
// 引用传递
func main() {//切片,可以扩容的数组s1 := []int{1, 2, 3, 4}fmt.Println("默认的数据", s1)//传入的是一个引用类型的数据update2(s1)fmt.Println("调用后的数据", s1)}
func update2(s2 []int) {fmt.Println("传递的数据", s2)s2[0] = 100fmt.Println("修改后的数据", s2)
}
函数变量的作用域
// 全局变量
var num int = 100func main() {temp := 100if b := 1; b <= 10 {//语句内的局部变量temp := 50fmt.Println(temp) //局部变量就近原则fmt.Println(b)fmt.Println(num)}fmt.Println(temp)fmt.Println(num)
}
func f1() {//局部变量a := 1fmt.Println(a)
}
函数递归
// 函数递归,自己调用自己
func main() {sum := getSum1(5)fmt.Println(sum)
}
func getSum1(n int) int {if n == 1 {return 1}return getSum1(n-1) + n}
defer 延迟函数执行
// defer 关闭操作
func main() {a := 10fmt.Println("a=", a)defer f(a) //参数已经传进去了,在最后执行a++fmt.Println("end a=", a)}
func f(s int) {fmt.Println("函数里面的a=", s)
}
函数本质的探讨
// func() 本身就是一种数据类型
// a1 如果不加括号函数就是一个变量
func main() {fmt.Printf("%T\n", a1)//定义函数类型的变量var a2 func(int, int)a2 = a1//他们地址是一样的fmt.Println(a1)fmt.Println(a2)a2(1, 2)
}
func a1(a, b int) {fmt.Println(a, b)
}
匿名函数的推导
// 匿名函数
func main() {b1()b2 := b1 //函数本身也是一个变量 加了括号就运行b2()//匿名函数f3 := func() {fmt.Println("我是b3函数")}f3()r1 := func(a, b int) int {//fmt.Println(a, b)//fmt.Println("我是b4函数")return a + b}(1, 2)fmt.Println(r1)}
func b1() {fmt.Println("我是b1函数")
}
回调函数
// 回调函数
// 高阶函数,根据go语言的数据类型的特点,可以将一个函数作为另一个函数的参数
// fun1() fun2()
// 将fun1函数作为fun2这个函数的参数
// fun2函数就叫做高阶函数,接收了一个函数作为参数的函数
// fun1函数,就叫做回调函数,作为另一个函数的参数
func main() {r1 := adda(1, 2)fmt.Println(r1)r2 := oper(3, 4, adda)fmt.Println(r2)r3 := oper2(8, 6, sub)fmt.Println(r3)r4 := oper(8, 4, func(a, b int) int {if b == 0 {fmt.Println("除数不能为0")return 0}return a / b})fmt.Println(r4)nan := func(a, b int) int {return a + b}(1, 2)fmt.Println(nan)}// 高阶函数
func oper(a, b int, fun func(int, int) int) int {r := fun(a, b)return r
}
func oper2(a, b int, fun func(int, int) int) int {r := fun(a, b)return r
}
func adda(a, b int) int {return a + b
}
func sub(a, b int) int {return a - b
}
函数闭包结构的理解
/*
一个外层函数中,有内层函数,该内层函数中,会操作外层函数的局部变量
并且该外层函数的返回值就是这个内层函数
这个内层函数和外层函数的局部变量,统称为闭包结构局部变量的生命周期就会发生改变,正常的局部变量会随着函数的调用为船舰,随着函数的结束二销毁
但是闭包结构中的外层函数的局部变量并不会随着外层函数的结束而销毁,因为内层函数还在继续使用
*/
func main() {r1 := increment()fmt.Println(r1)v1 := r1()fmt.Println(v1)v2 := r1()fmt.Println(v2)fmt.Println(r1())fmt.Println(r1())fmt.Println(r1())//如果调用r2表示r1外层函数已经销毁,但是函数内层的i还是存在//正常情况下r2的创建r1应该已经销毁,因为r2重新调用了increment()r2 := increment()v3 := r2()fmt.Println(v3)fmt.Println(r1())fmt.Println(r1())
}// 自增
func increment() func() int {//局部变量i := 0//定义一个匿名函数,给变量自增并返回fun := func() int { //内层函数,没有执行i++return i}return fun
}