Go 语言函数
Go 语言函数
1. 概述
函数是基本的代码块,用于执行一个任务
Go 语言最少有一个 main() 函数
你可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务
函数声明告诉了编译器函数的名称,返回类型,和参数
Go 语言标准库提供了多种可动用的内置的函数。
例如,len()函数可以接受不同类型参数并返回该类型的长度。如果我们传入的是字符串则返回字符串的长度,如果传入的是数组,则返回数组中包含的元素个数。
2. 函数的定义
Go 语言函数定义格式如下:
1 | func 函数名 (参数列表) (返回值列表) |
无参数返回值
1 2 3 | func test() { } |
传参有返回值
1 2 3 4 | func test(a int ,b int ) int { return n } |
传参有多个返回值
1 2 3 4 | func result(a int ,b int )( int , int ) { return a+b,a*b } |
- 示例: 定义max()函数传入两个整形参数 num1 和 num2,并返回这两个参数的最大值
1 2 3 4 5 6 7 8 9 10 11 12 | /* 函数返回两个数的最大值 */ func max(num1, num2 int ) int { /* 声明局部变量 */ var result int if num1 > num2 { result = num1 } else { result = num2 } return result } |
3. 函数调用
- 当创建函数时,你定义了函数需要做什么,通过调用该函数来执行指定任务,调用函数,向函数传递参数,并返回值
函数的调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | package main import "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 |
函数返回多个值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | package main import "fmt" func swap(x, y string ) ( string , string ) { return y, x } func main() { a, b := swap( "hello" , "world" ) fmt.Println(a, b) } //输出结果如下 world hello |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | package main import "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 |
4. 函数参数
- 函数如果使用参数,该变量可称为函数的
形参
- 形参就像定义在函数体内的局部变量
- 调用函数,可以通过两种方式来传递参数
默认情况下,Go 语言使用的是值传递,即在调用过程中不会影响到实际参数
传递类型 | 描述 |
---|---|
值传递 | 值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数 |
引用传递 |
引用传递是指在调用函数时将实际参数的 |
值类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | package main import "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: 10 num2: 20 交换后 num1: 10 num2: 20 |
总结:
可以看到,实际的值并没有交换,只是把实际参数给复制了一份传递到了函数中去,并不会影响原本的实际参数
引用类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | package main import "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 |
5. 函数作为实参
-
可以很灵活的创建函数,并作为另一个函数的实参
-
示例:
使用math
数学包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | package main import ( "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的绝对值: 10 5.2向下取整: 6 5.8向下取整: 5 11除3的余数: 2 取整数,取小数 5 0.2599999999999998 3的2次方 9 10的4次方 10000 8的开平方 2.8284271247461903 8的开立方 2 圆周率 3.141592653589793 |
6. 回调函数
回调函数是一个被作为参数传递的函数,可以大大提升编程的效率。
函数执行流程描述
① 首先在main函数中调用了test1()函数,这时候test1会顺着去加载里面的语句 1、2,直到语句2加载完后,加载回调函数test2,test2会执行函数体内的语句 1、2,3;
② 当test2函数体中语句执行完成,回调函数的生命周期将结束,如果有返回值将返回,没有则结束;
③ 当回调函数执行完以后,将继续执行test1函数中的语句 3,4,执行完以后test1函数的生命周期也将结束
④ test1函数结束以后就会返回main主函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | package main import "fmt" //声明函数类型 type cback func( int ) int func 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: 1 test_back函数:语句2 |
7. 匿名函数
- 匿名函数就是没有函数名的函数,匿名函数多用于实现回调函数和闭包
- 匿名函数是一个"内联"语句或表达式
- 匿名函数的优越性在于可以直接使用函数内的变量,不必申明
- 匿名函数的定义格式如下:
1 2 3 | func(参数)(返回值){ 函数体 } |
匿名函数的执行方式如下
- ① 把匿名函数赋值给变量
1 2 3 4 5 6 7 8 9 10 11 12 13 | package main import "fmt" func main() { sayHello := func() { fmt.Println( "匿名函数" ) } sayHello() } //执行结果如下 匿名函数 |
- ② 立即执行函数
1 2 3 4 5 6 7 8 9 10 11 12 | package main import "fmt" func main() { func() { fmt.Println( "匿名函数" ) }() //匿名函数定义完成加上()可以直接进行执行 } //执行结果如下 匿名函数 |
8. 闭包
- 闭包可以理解为
定义在一个函数内部的函数
,本质上闭包是将函数内部和外部连接起来的桥梁,或者说是函数和其引用环境的组合体 - 闭包指的是一个函数和与其相关的引用环境组合而成的实体。简单来说,
闭包=函数+引用环境
闭包示例 ①
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | package main import "fmt" //定义一个函数,他的返回值是一个函数 //把函数作为返回值 func a() func() { name := "world" return func() { fmt.Println( "hello" , name) //先在函数内找name变量,找不到就上函数体外层去找 } } func main() { //闭包 = 函数+外出变量的引用 r := a() //r就是一个闭包 r() //相当于执行了a函数的匿名函数 } //执行结果 hello world |
示例 ②
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | package main import ( "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.jpg test.txt |
示例 ③
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | package main import "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: 300 ret2: 100 |
- 示例 ④
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | //回调函数是把函数作为传递参数,而闭包则是把函数作为一个返回值 package main import "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做自增 1 2 3 使用nextNumber1做自增 1 2 3 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具