go学习笔记
基础
go 定义变量的几种方式
常量的声明
go基本数据类型
go语言中的流程控制
golang中的数组
切片
golang中的map 详解
golang 函数详解
内置函数 panic/recover
golang time包 以及日志函数
golang中的指针
golang 中的结构体
Golang 结构体 和 json互相转换 序列化 反序列化
Golang 中的 go mod 以及 Golang包 详解
golang 中的接口
golang goroutine channel 实现并发 和 并行
channel
goroutine 互斥锁 读写互斥锁
golang 反射
golang 标准库
io
strconv
工具 + blog
进程 线程 协程
空接口 类型断言
为Go项目编写Makefile
减小 Go 代码编译后的二进制体积
go windows下编译linux可执行文件
本文档使用 MrDoc 发布
-
+
首页
golang 函数详解
## golang 函数详解 ### 定义函数 ``` func sum(a int, b int) int { return a + b } func main() { i := sum(1, 100) fmt.Printf("i: %v\n", i) } ``` ### 可变参数 函数的可变参数,可变参数是指函数的参数数量不固定。Go 语言中的可变参数通过在参数名后加... 来标注 ``` func num(a ...int) { fmt.Printf("a: %v a的类型 %T\n", a, a) } func str(b ...string) { fmt.Printf("b: %v b的类型 %T\n", b, b) } func main() { num(12, 32, 445, 665) //a: [12 32 445 665] a的类型 []int //a 是一个slice类型 str("haha", "hehe") //b: [haha hehe] b的类型 []string //b 是一个slice类型 } ``` ### 多个返回值 ``` func sum(a int, b int) (int, int) { //返回 a+b a-b 的结果 return a + b, a - b } func main() { i, i2 := sum(20, 10) fmt.Printf("i: %v\n", i) fmt.Printf("i2: %v\n", i2) } ``` 返回值命名:函数定义时可以给返回值命名,并在函数体中直接使用这些变量,最后通过return 关键字 ``` func sum(a int, b int) (sum int, sub int) { //sum 与 sub 已经在函数中申明 所以不用再声明 sum = a + b sub = a - b return sum, sub } func main() { i, i2 := sum(20, 10) fmt.Printf("i: %v\n", i) fmt.Printf("i2: %v\n", i2) } ``` ### 函数变量的作用域 ``` func num(a []int) []int { sort.Ints(a) //sort.Ints 可以把 int slice中的元素 进行升序排列 return a } func main() { var a = []int{10, 23, 32, 43, 2, 5, 6, 7, 234, 1111} i := num(a) fmt.Printf("i: %v\n", i) //i: [2 5 6 7 10 23 32 43 234 1111] } ``` 函数变量的作用域: * 全局变量:全局变量是定义在函数外部的变量,它在程序整个运行周期内都有效(全局作用域) * 局部变量:局部变量是函数内部定义的变量,函数内定义的变量无法在该函数外使用(局部作用域) ## 函数类型 ### 定义函数类型 我们可以使用type关键字来定义一个函数类型,具体格式如下 ``` type name func (int,int)int ``` ``` type calc func(int, int) int func sum(a int, b int) int { return a + b } func main() { var c calc c = sum i := c(2, 3) fmt.Printf("c: %v c type %T\n", c, c) fmt.Printf("i: %v i type %T\n", i, i) /* c的类型是 calc c: 0x23ca00 c type main.calc i: 5 i type int */ } ``` ### 函数当作参数 ``` type calc func(int, int) int func sum(a int, b int) int { fmt.Println("运行 sum") return a + b } func sub(a int, b int) int { fmt.Println("运行 sub") return a - b } func mycalc(a int, b int, c calc) int { i := c(a, b) return i } func main() { i := mycalc(30, 20, sub) fmt.Printf("i: %v\n", i) i2 := mycalc(40, 20, sum) fmt.Printf("i2: %v\n", i2) } /* 运行 sub i: 10 运行 sub i2: 20 */ ``` ### 函数作为返回值 ``` func sum(a int, b int) int { return a + b } func sub(a int, b int) int { return a - b } type calc func(int, int) int func choose(o string) calc { switch o { case "+": fmt.Println("return sum") return sum case "-": fmt.Println("return sub") return sub default: fmt.Println("return nill") return nil } } func main() { c := choose("+") if c == nil { fmt.Println("不支持") } i := c(20, 30) fmt.Printf("i: %v\n", i) } /* return sum i: 50 */ ``` ### 匿名函数 ``` func(参数)(返回值){ 函数体 } ``` ``` func main() { func() { fmt.Println("haha") }() var a = func(a int, b int) int { return a + b } i := a(10, 30) fmt.Printf("i: %v\n", i) } ``` 匿名 自执行函数 ``` func(a, b int) { fmt.Println(a + b) }(10, 20) // 30 ``` ### 函数的递归调用 ### 闭包 全局变量的特点: * 常驻内寸 * 污染全局 局部变量的特点: * 不常住内存 * 不污染全局 闭包: * 可以让一个变量常驻内存 * 可以让一个变量不污染内存 1.闭包是指有权访问另一个函数作用域中的变量的函数。 2.创建闭包的常见的方式就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量。 注意:由于闭包里作用域返回的局部变量资源不会被立刻销毁回收,所以可能会占用更多的内存。过度使用闭包会导致性能下降,建议在非常有必要的时候才使用闭包。 闭包可以理解成“定义在一个函数内部的函数”。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。或者说是函数和其引用环境的组合体。 例子1: ``` func a() func() int { var i int = 10 return func() int { return i + 1 } } func main() { f := a() // a() 表示执行方法 a表示f=a方法 f2 := f() fmt.Printf("f2: %v\n", f2) } ``` 例子2: ``` func a() func(a int) int { var i int = 10 return func(a int) int { i = i + a //return i+a 不可以这样写 ,这样写只是把结果返回了,i变量的值没有改变,下次调用的时候还是旧的值 return i } } func main() { f := a() // a() 表示执行方法 a表示f=a方法 f2 := f(10) f3 := f(20) f4 := f(30) fmt.Printf("f2: %v\n", f2) //f2: 20 fmt.Printf("f3: %v\n", f3) //f3: 40 fmt.Printf("f4: %v\n", f4) //f4: 70 } ``` ### defer 语句 Go语言中的defer 语句会将其后面跟随的语句进行延迟处理。在defer归属的函数即将返回时,将延迟处理的语句按defer定义的逆序进行执行,也就是说,先被defer 的语句最后被执行,最后被defer的语句,最先被执行。 ``` func a() { fmt.Println("a 方法被执行") } func main() { defer fmt.Println("第一个被 defer 的语句") //第一个被defer 的语句 最后执行 a() defer fmt.Println("第二个被 defer 的语句") defer fmt.Println("最后一个被defer 的语句") // 最后被 defer 的语句 先执行 /* 被defer 语句定义的 要等所有方法跑完后才执行 a 方法被执行 最后一个被defer 的语句 第二个被 defer 的语句 第一个被 defer 的语句 */ } ``` **defer 在命名返回值 和 匿名返回 函数中变现不一样** ``` func a() int { //该方法是 匿名返回值 所以会返回0 var i int // i 默认值为0 defer func() { //匿名函数被defer i++ }() return i // 先retrun 然后再执行defer } func b() (v int) { //该方法是已经 命名返回值 defer func() { v++ }() return v } func main() { i := a() //执行 a() fmt.Printf("i: %v\n", i) // 输出 i:0 i2 := b() //执行 b() fmt.Printf("i2: %v\n", i2) //输出 i2:1 } ``` ![](/media/202208/2022-08-04_164500_3579920.2113888808362362.png)
admin
2024年1月21日 22:24
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码