函数是基本的代码块,用于执行一个任务
Go 语言最少有一个 main() 函数
你可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务
函数声明告诉了编译器函数的名称,返回类型,和参数
Go 语言标准库提供了多种可动用的内置的函数。
例如,len()函数可以接受不同类型参数并返回该类型的长度。如果我们传入的是字符串则返回字符串的长度,如果传入的是数组,则返回数组中包含的元素个数。
Go 语言函数定义格式如下:
func 函数名 (参数列表) (返回值列表)
无参数返回值
func test() {}传参有返回值
func test(a int,b int) int { return n}传参有多个返回值
func result(a int,b int)(int,int) { return a+b,a*b}
/* 函数返回两个数的最大值 */func max(num1, num2 int) int { /* 声明局部变量 */ var result int if num1 > num2 { result = num1 } else { result = num2 } return result}
函数的调用
package mainimport "fmt"func main() { var ( a int = 100 b int = 200 ) var result int //函数调用,注意返回值和接受值类型必须一致 result = max(a, b) fmt.Println("最大值为:", result)}/* 函数返回两个数的最大值 */func max(num1, num2 int) int { /* 声明局部变量 */ var result int if num1 > num2 { result = num1 } else { result = num2 } return result}//输出结果如下最大值为: 200
函数返回多个值
package mainimport "fmt"func swap(x, y string) (string, string) { return y, x}func main() { a, b := swap("hello", "world") fmt.Println(a, b)}//输出结果如下world hello
package mainimport "fmt"func main() { var ( a, b = multi_value(3, 5) ) fmt.Println("和:", a, "\n积:", b)}func multi_value(num1, num2 int) (int, int) { result1 := num1 + num2 result2 := num1 * num2 //返回两数和,两数乘积 return result1, result2}//输出结果如下和: 8 积: 15
形参默认情况下,Go 语言使用的是值传递,即在调用过程中不会影响到实际参数
| 传递类型 | 描述 |
|---|---|
| 值传递 | 值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数 |
| 引用传递 | 引用传递是指在调用函数时将实际参数的 |
package mainimport "fmt"func main() { var ( num1 = 10 num2 = 20 ) fmt.Println("交换前\n") fmt.Printf("num1: %v\n", num1) fmt.Printf("num2: %v\n", num2) swap(num1, num2) fmt.Println("\n交换后\n") fmt.Printf("num1: %v\n", num1) fmt.Printf("num2: %v\n", num2)}//两数交换func swap(a, b int) { a, b = b, a}//输出结果如下交换前num1: 10num2: 20交换后num1: 10num2: 20
总结:
可以看到,实际的值并没有交换,只是把实际参数给复制了一份传递到了函数中去,并不会影响原本的实际参数
package mainimport "fmt"func main() { var ( num1 = 11 num2 = 22 ) fmt.Println("交换前") fmt.Printf("num1: %v, num2: %v\n", num1, num2) fmt.Println("-----------------") swap(&num1, &num2) fmt.Println("交换后") fmt.Printf("num1: %v, num2: %v\n", num1, num2)}//引用类型交换func swap(a, b *int) { *a, *b = *b, *a}//输出结果如下交换前num1: 11, num2: 22-----------------交换后num1: 22, num2: 11
可以很灵活的创建函数,并作为另一个函数的实参
示例:
使用math数学包
package mainimport ( "fmt" "math")func main() { //函数变量 result := func(x float64) float64 { return math.Sqrt(x) } fmt.Println(result(9)) fmt.Println("-10的绝对值:", math.Abs(-10)) fmt.Println("5.2向下取整:", math.Ceil(5.2)) fmt.Println("5.8向下取整:", math.Floor(5.8)) fmt.Println("11除3的余数:", math.Mod(11, 3)) fmt.Println("取整数,取小数") fmt.Println(math.Modf(5.26)) fmt.Println("3的2次方", math.Pow(3, 2)) fmt.Println("10的4次方", math.Pow10(4)) fmt.Println("8的开平方", math.Sqrt(8)) fmt.Println("8的开立方", math.Cbrt(8)) fmt.Println("圆周率", math.Pi)}//输出结果如下3-10的绝对值: 105.2向下取整: 65.8向下取整: 511除3的余数: 2取整数,取小数5 0.25999999999999983的2次方 910的4次方 100008的开平方 2.82842712474619038的开立方 2圆周率 3.141592653589793
回调函数是一个被作为参数传递的函数,可以大大提升编程的效率。
函数执行流程描述
① 首先在main函数中调用了test1()函数,这时候test1会顺着去加载里面的语句 1、2,直到语句2加载完后,加载回调函数test2,test2会执行函数体内的语句 1、2,3;
② 当test2函数体中语句执行完成,回调函数的生命周期将结束,如果有返回值将返回,没有则结束;
③ 当回调函数执行完以后,将继续执行test1函数中的语句 3,4,执行完以后test1函数的生命周期也将结束
④ test1函数结束以后就会返回main主函数

package mainimport "fmt"//声明函数类型type cback func(int) intfunc main() { //对回调函数进行隐匿,能起到保护作用,并且提高程序的运行效率 test_cback(1, callback)}//测试函数,用来调用回调函数func test_cback(x int, f cback) { fmt.Println("test_back函数:语句1") f(x) fmt.Println("test_back函数:语句2")}//回调函数func callback(a int) int { fmt.Println("回调函数callback:", a) return a}//执行结果如下test_back函数:语句1回调函数callback: 1test_back函数:语句2
func(参数)(返回值){ 函数体}
匿名函数的执行方式如下
package mainimport "fmt"func main() { sayHello := func() { fmt.Println("匿名函数") } sayHello()}//执行结果如下匿名函数
package mainimport "fmt"func main() { func() { fmt.Println("匿名函数") }() //匿名函数定义完成加上()可以直接进行执行}//执行结果如下匿名函数
定义在一个函数内部的函数,本质上闭包是将函数内部和外部连接起来的桥梁,或者说是函数和其引用环境的组合体闭包=函数+引用环境闭包示例 ①
package mainimport "fmt"//定义一个函数,他的返回值是一个函数//把函数作为返回值func a() func() { name := "world" return func() { fmt.Println("hello", name) //先在函数内找name变量,找不到就上函数体外层去找 }}func main() { //闭包 = 函数+外出变量的引用 r := a() //r就是一个闭包 r() //相当于执行了a函数的匿名函数}//执行结果hello world

示例 ②
package mainimport ( "fmt" "strings")//使用闭包做文件后缀名检测func makeSuffixFunc(suffix string) func(string) string { return func(name string) string { if !strings.HasSuffix(name, suffix) {//判断字符串后缀的格式 return name + suffix } return name }}func main() { jpgFunc := makeSuffixFunc(".jpg") txtFunc := makeSuffixFunc(".txt") fmt.Println(jpgFunc("test")) fmt.Println(txtFunc("test"))}//执行结果如下test.jpgtest.txt
示例 ③
package mainimport "fmt"func calc(base int) (func(int) int, func(int) int) { add := func(i int) int { base += i return base } sub := func(i int) int { base -= i return base } return add, sub}func main() { x, y := calc(100) ret1 := x(200)//调用x的时候传入值为200;base = 100 + 200 fmt.Printf("ret1: %v\n", ret1) ret2 := y(200)//base = 300 - 200 fmt.Printf("ret2: %v\n", ret2)}//输出结果如下ret1: 300ret2: 100
//回调函数是把函数作为传递参数,而闭包则是把函数作为一个返回值package mainimport "fmt"func close_package() func() int { i := 0 return func() int { i += 1 return i }}func main() { //定义函数 使用闭包做+1操作 nextNumber := close_package() fmt.Println("使用nextNumber做自增") fmt.Println(nextNumber()) fmt.Println(nextNumber()) fmt.Println(nextNumber()) fmt.Println("使用nextNumber1做自增") nextNumber1 := close_package() fmt.Println(nextNumber1()) fmt.Println(nextNumber1()) fmt.Println(nextNumber1())}//执行结果如下使用nextNumber做自增123使用nextNumber1做自增123