Golang 函数、包
一、函数
fun 方法名称(形参列表) 返回值列表 {
}
二、包
包的基本概念
go的每一个文件都是属于包的,也就是说go是以包的形式来管理文件和项目目录结构。
包的作用
1)区分相同名字的函数、变量等表示符。
2)当程序文件很多时,可以很好的管理项目
3)控制函数、变量等访问范围,即作用域
包的打包和引入
打包基本语法
package “包名”
引入包的基本语法
import “包的路径”
注意:包中的方法名称开头字母要大写,否则即使引入包也访问不了方法,因为小写的方法名称表示“私有方法”。
第一步:创建一个文件,并写函数。在utils文件夹下创建一个utils.go文件(包),并编写 Cal方法。
package utils import ( "fmt" ) //为了让其他包的文件使用Cal函数,需要将"C"大写,类似于其他语言的“public” func Cal(n1 float64,n2 float64,operator byte) float64{ var res float64 switch operator { case '+': res = n1 + n2 case '-': res = n1 - n2 case '*': res = n1 * n2 case '/': res = n1 / n2 default: fmt.Println("操作符号错误...") } return res }
第二步:main.go文件中引入包
注意:默认引入路径是从"src"开始,即"src"是可以不用写
package main import ( "fmt" "go_code/fordemo/utils" )
第三步:调用方法
注意:调用格式为:包名.方法名(参数)
package main import ( "fmt" "go_code/chapter04/fordemo/utils" ) func main(){ var n1 float64 = 1.2 var n2 float64 = 2.3 var operator byte = '+' result := utils.Cal(n1,n2,operator) fmt.Println("result = ",result) }
三、init函数(初始化)
基本介绍
每一个源文件都可以包含一个init函数,该函数会在main函数执行前,被go运行框架调用,也就是说init会在main函数前被调用。
package main import ( "fmt" ) //init函数,通常可以在init函数中完成初始化工作 func init() { fmt.Println("init()...") } func main(){ fmt.Println("main()...") }
init的注意事项和细节
1)如果一个文件同时包含全局变量定义,init函数和main函数,则执行的流程是全局变量定义->init函数->mian函数
package main import ( "fmt" ) //定义一个全局变量 var age =test() //第一个执行 //此函数用于测试 全局变量age的执行顺序 func test() int { fmt.Println("test()") return 90 } //第二个执行 //init函数,通常可以在init函数中完成初始化工作 func init() { fmt.Println("init()...") } //第三个执行 func main() { fmt.Println("main()...age = ",age) }
2)init函数最主要的作用,就是完成一些初始化的工作
四、匿名函数
介绍
Go支持匿名函数,如果我们某个函数只是希望使用一次,可以考虑使用匿名函数,匿名函数也可以实现多次调用。
匿名函数使用方式1(项目开发中常用)
在定义匿名函数时就直接调用
package main import ( "fmt" ) func main() { //在定义匿名函数时就直接调用 res1 := func(n1 int, n2 int) int { return n1 + n2 }(10, 20) fmt.Println("res1 = ", res1) }
匿名函数使用方式2
将匿名函数赋给一个变量(函数变量),在通过该变量来调用匿名函数
package main import ( "fmt" ) func main() { //将匿名函数func(n1 int,n2 int) int 赋给a变量 //则a的数据类型就是函数类型,此时,我们可以通过a完成调用 a := func(n1 int,n2 int) int { return n1 - n2 } rest2 := a(10,30) fmt.Println("res2 = ",rest2) rest3 := a(90,30) fmt.Println("res3 = ",rest3) }
全局匿名函数
如果将匿名函数赋给一个全局变量,那么这个匿名函数,就成为一个全局函数,可以在程序有效。
package main import ( "fmt" ) var ( //fun1 就是一个全局匿名函数 Fun1 = func (n1 int,n2 int) int { return n1 * n2 } ) func main() { //全局匿名函数的使用 res4 := Fun1(4,9) fmt.Println("rest4 = ",res4) }
五、闭包
介绍
闭包就是一个函数和与其关联的引用环境组合的一个整体(实体)
package main import ( "fmt" ) //累加器 func AddUpper() func (int) int { var n int = 10 return func (x int) int { n = n + x return n } } func main(){ //使用前面的代码 f := AddUpper() fmt.Println(f(1)) //结果是 11 fmt.Println(f(2)) //结果是 13 fmt.Println(f(3)) //结果是 16 }
对上面代码的说明和总结
1)AddUpper 是一个函数,返回的数据类型是 fun(int) int
2) 闭包的说明
返回的是一个匿名函数,但是这个匿名函数引用到函数外的n,因此这个匿名函数就和n行成一个整体,构成闭包。
3)可以这样理解:闭包是一个类,函数是操作,n是字段。函数和它使用到的n构成一个闭包。
4)当我们反复调用f函数时,因此n是初始化一次,因此每调用一次就进行累计。
5)闭包的关键就是要分析出返回的函数它使用到哪些变量,因为函数和它引用到的变量共同构成闭包。
六、defer语句
在函数中,程序员经常需要创建资源(比如:数据库连接、文件句柄、锁等),为了在函数执行完毕后,及时的释放资源,go的设计者提供defer(延迟机制)。
defer介绍
package main import ( "fmt" ) func sum(n1 int, n2 int) int { //当执行到defer时,暂时不执行,会将defer后面的语句压入到独立的栈(defer栈) //当函数执行完毕后,在从defer栈,按照先入后出的方式出栈执行。 defer fmt.Println("ok1 n1 = ", n1) //3.ok1 n1 = 10 defer fmt.Println("ok2 n2 = ", n2) //2.ok2 n2 = 20 res := n1 + n2 fmt.Println("ok3 res = ", res) // 1. ok3 = 30 return res } func main() { res := sum(10, 20) fmt.Println("res = ", res) //4.res = 30 }
defer的细节说明
1)当go执行到一个defer时,不会立即执行defer后的语句,而是将defer后的语句压入到一个栈(暂且叫做defer栈)中,然后继续执行函数下一个语句。
2)当函数执行完毕后,在从defer栈中,依次从栈顶取出语句执行。
3)在defer将语句放入到栈时,也会将相关的值拷贝同时入栈。
package main import ( "fmt" ) func sum(n1 int, n2 int) int { //当执行到defer时,暂时不执行,会将defer后面的语句压入到独立的栈(defer栈) //当函数执行完毕后,在从defer栈,按照先入后出的方式出栈执行。 defer fmt.Println("ok1 n1 = ", n1) //3.ok1 n1 = 10(将值也放入栈中) defer fmt.Println("ok2 n2 = ", n2) //2.ok2 n2 = 20 res := n1 + n2 //30 n1++ //11 fmt.Println("ok3 res = ", res,"n1 = ",n1) // 1. ok3 res = 30 n1 = 11 return res } func main() { res := sum(10, 20) fmt.Println("res = ", res) //4.res = 30 }
defer的最佳实践
defer最主要的价值在,当函数执行完毕后,可以及时的释放函数创建的资源。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!