GoLang:函数、方法
学习自:Go教材80、117页
1、函数
A、函数
函数定义在main函数之外
func 函数名(参数列表)(返回类型列表) {
语句;
return 返回值;
}
①无参函数
func say(){
fmt.println("Hello world!")
}
②有参无返回值
func say(name string){
fmt.Println("Hello ",name)
}
③无参有返回值(若返回值只有一个,则不用加括号)
func sum() int {
return 1+1
}
④有参有返回值
func sum(a int,b int) int {
return a+b
}
⑤指定返回值的名称
func sum()(res int){
res=1+1
return
}
⑥多个返回值(完全体)
func calculate(a int,b int)(sum int,sub int){
sum=a+b
sub=a-b
return
}
⑦相同(返回值/参数)类型,只写最后一个即可
func calculate(a,b int)(sum,sub int){
sum=a+b
sub=a-b
}
补充:
函数的定义位置在使用位置之前还是之后对函数的正常使用无影响。
B、值传递、引用传递
值类型:int、float、bool、string、数组、struct
引用类型:指针、slice、map、channel
说明:
- 值类型在栈中分配空间,引用类型在堆中
- 作为函数参数传递到函数内时,值传递是拷贝传递,引用传递是引用传递
- 在函数体内对值参数的修改不会影响函数外的值,对引用类型参数的修改,会影响到函数外的值。
例子
值传递
引用传递
C、匿名函数
应用场景:
- 某个函数只用到了一次
- 执行一些不确定的操作
①直接调用
func (s string){
fmt.Println(s)
}("hello lnj")
②保存到变量
a:=func(s string){
fmt.Println(s)
}
a("hello lnj")
③作为参数
test( func(s string){
fmt.Println(s)
})
func test(f func(s string)){
f("hello lnj")
}
④作为返回值
res:=test()
res(10,20)
func test() func(int,int){
return func(a int,b int){
fmt.Println(a+b)
}
}
D、闭包
闭包是一个特殊的匿名函数,它是匿名函数和相关引用环境组成的一个整体。
只要在匿名函数中用到了外界的变量,那么这个匿名函数就是一个闭包,在闭包中对外界变量的修改和直接在外界修改的效果相同。只要闭包还在使用外部变量,那么外部变量就会一直存在(哪怕这个变量不是在main中定义)
①经典闭包
②修改外部变量,导致外部变量自身也会发生变化
③闭包未结束,则外部变量一直存在(哪怕这个外部变量并非在main中定义的),且一直维持同一个变量而非新创建
E、延迟调用defer
常用于释放资源、解除锁定、错误处理
作用方式:无论在何处注册defer,它都会在所属函数执行完毕之后才会执行,并且如果注册了多个defer,会按照后进先出的原则执行。
基于这种特性,可以在资源打开的同时,就用defer来声明它的关闭,因为无论如何defer都会在所属函数执行完毕后才会执行
F、init函数
golang中存在两个保留的函数:
- init函数:应用于所有的package
- main函数:只能应用于main包
这两个函数在定义时不能有参数、返回值。
init函数的作用:处理当前文件的初始化操作,存放一些准备工作。
说明
- go会自动调用main、init,因此我们不能手动调用它们。
- main包必须包含一个main(),但每个包中的init()都是可选的
- 一个包中可以写任意多个init(),但是最好还是只写一个init
- 执行顺序:main包→常量→全局变量→init()→main()→Exit
执行顺序:const→var global...→init()→main()→exit
- 多个包代码的执行顺序
2、方法
1)定义
1 2 3 | func (接收者 数据类型)方法名(形参)(返回值){ 方法体 } |
2)说明
①方法本质上是一个特殊函数,只是它是和某种属性类型绑定在一起的;
②方法一般用于将函数和结构体进行绑定,让结构体除了保存数据外还能具备某些行为
③函数与数据类型绑定的格式:在函数名之前加上(接收者 数据类型),即可将函数和某种数据类型绑定在一起(见定义部分的写法)
3)例子
给结构体添加一个方法,使该结构体除了可以保存数据,还具备说出自己名字和年龄的行为(有点像是类方法,但是其定义和实现是在结构体之外,结构体只具备表达数据结构的能力):
1 2 3 4 5 6 7 8 9 10 11 12 13 | type Person struct { name string age int } func (p Person)say(){ fmt.Println( "my name is" ,p.name, "my age is" ,p.age) } func main(){ per := Person{ "lnj" ,33} per.say() } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性