基础知识:
函数定义组成部分:
函数声明关键字func、函数名、参数列表、返回列表和函数体
func funcName(param-list)(result-list){
function-body
}
注意:
函数名遵循标识符的命名规则,首字母的大小写决定该函数在其他包的可见性:大写时其他包可见,小写时只有相同的包可以访问
函数特点:
1、函数可以没有输入参数,也可以没有返回值(默认返回0),可以多值返回
2、多个相邻的相同类型的参数可以简写,如下
func add(a,b int)int{ //a int ,b int
...
}
3、支持有名的返回值,参数名就相当于函数体内最外层的局部变量,命名返回值变量会被初始化为类型零值,最后的return可以不带参数名直接返回
func add(a,b int)(sum int){
sum = a+b
return //相当于return sum
}
4、不支持默认值参数
5、不支持函数重载
6、不支持函数嵌套,严格地来说不支持命名函数的嵌套定义,但支持嵌套匿名函数,如下:
func add(a,b int)(sum int){
x := func(x,y int)int{
return x+y
}
return x(a,b)
}
7、Go函数实参到形参的传递永远都是值拷贝。
Go函数支持不定数目的形参,声明使用param …type
特点:
1、所有的不定参数类型必须是相同的
2、不定参数必须是函数的最后一个参数
3、不定参数名在函数体内相当于切片,对切片的操作同样适用于不定参数
4、切片可以作为参数传递给不定参数,切片名后要加上“…”,如:
func sum(arr ...int)(sum int){
for _,v := range arr{
sum += v
}
return
}
func main(){
slice := []int{1,2,3}
array := [...]int{1,2,3,4}
//数组不可以作为实参传递给不定参数的函数
sum(slice...)
}
5、形参为不定参数的函数和形参为切片的函数类型不相同
函数签名
其实也就是函数类型,一个函数的类型就是函数定义首行去掉函数名、参数名,可以使用fmt.Printf的%T格式化参数打印函数类型,未初始化的函数类型的变量的默认值是nil
fmt.Printf("%T\n",函数名)
两个函数类型相同的条件是:拥有相同的形参列表和返回值列表(列表元素的次序、个数和类型都相同),形参名可以不同
func add(a,b int) int {return a+b}
func sub(x,y int) (c int){ ...}
这两个函数的函数类型一样
type op func(int,int) int //函数类型作为形参
func do(f op,a,b int)int{
return f(a,b)
}
匿名函数
匿名函数可以看作函数字面量。所有直接使用函数类型变量的地方都可以由匿名函数代替,可以直接赋值给函数变量,可以当做实参,也可以作为返回值,还可以直接被调用。
var sum = func(a,b int)int{
return a+b
}
func op(f func(int,int)int, a,b int)int{
...
}
op(func(x,y int)int{
return x+y
},1,2)
后续补充
Go提供了两种处理错误的方式:
panic函数以及recover函数:
panic的参数是一个空接口类型interface{},所以任意类型的变量都可以传递给panic;recover()用来捕获panic,阻止panic继续向上传递
可以和defer搭配使用,defer里面的panic能够被后续执行的defer捕获;recover()也可以和defer使用,但是recover只有在defer后面的函数体内被直接调用才能捕获panic终止异常,否则返回nil,异常继续向外传递,如图:
在延迟defer调用的情景中,可以出现连续多个panic被抛出,但只有最后一次panic能够被捕获,如下:
errorl类型:
Go语言典型的错误处理方式是将error作为函数最后一个返回值,在调用函数时,通过检测其返回的error值是否为nil来进行错误处理。