这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天,本次是对于go语言中func函数的学习。
Go 语言 func函数
函数是结构化编程中最小的模块单元,将复杂的算法过程分解为若干个小任务(代码块),使程序的结构性更清晰。
在Go语言中,当函数执行到代码块最后一行 "}"之前或者return语句时会退出结束,其中return可以带有0个或多个参数,return语句可以用来结束for死循环或者结束一个Go协程(Goroutine)
定义语法:
func 函数名(参数列表)(返回值列表){
• //函数体
}
func funcName(input1 type1,input2 type2)(out1 type1,out2 type2){
• //逻辑代码
• //返回多个值
• return value1,value2
}
- (1)func-----声明函数funcName
-
(2)函数可以有一个或者多个参数,每个参数后面带有类型,多个参数之间通过”,“分割,同时函数可以返回多个值
- (3)返回值声明了两个变量output1和output2,可以不声明,直接只保留两个类型
- (4)如果只有一个返回值且不声明返回值变量,则可以省略,包括返回值的符号。如果没有返回值,则直接省略最后的返回信息;如果有返回值,则必须在函数的外层添加return语句。
- (5)函数的返回值类型和变量定义的数据类型一样,并且都要遵循”后置原则“
1.若参数列表中若干个相邻参数的类型相同,则可在参数列表中省略前面的变量类型声明
func Add(a,b int) int{ //a,b类型都为int,并且go语言中左花括号的位置强制要求放在括号后面
//函数体
}
2.支持多返回值、命名返回值
多值返回一般用于错误处理
func sumMulti(i, j int) (int, int, int) { // 多返回值
return i+j, i*j, i-j
}
func Split(sum int) (x, y int) { // 命名返回
x = sum * 4 / 9
y = sum - x
return //不用带上变量名,直接在函数里面初始化了
}
3.不定参数
func myfunc(arg ... int){} //这些参数的类型都是int,调用时可以接收任意数目的参数,arg是int的slice
func sum(nums...int){
total :=0
for _,num :=range nums{
total+=num
}
fmt.Println(total)
}
func main(){
arr :=[]int{1,2,3}
sum(arr...) //不定参数传参
}
4.传值与传指针
当传一个参数值到被调用函数里面时,实际是传了这个值的一份copy,当在被调用函数中修改参数值时,调用函数中对应的实参不会发生改变,修改的只是copy的值。
func add(a int) int{
a=a+1
return a
}
func main(){
a :=3
fmt.Println("a+1=",add(a)) //a+1=4
fmt.Println("a=",a) //a=3
}
add接收的参数是a的copy,并不是a本身,所以修改的只是x的copy的值,即在函数调用中执行的结果会加1,但是a本身还是并未改变。
想要实现传a本身,首先变量在内存中是存放在一定地址上,修改变量实际是修改变量地址处的内存,即只有add函数知道a变量的地址,才能修改变量a本身的值。所以在传参时,需要将a所在地址&x传入函数,并将函数的参数类型由int修改为*int,改为指针类型。此时虽然也是一份copy,但是copy的是指针。
func add(a *int) int{
a=a+1
return a
}
func main(){
a :=3
fmt.Println("a+1=",add(&a)) //a+1=4
fmt.Println("a=",a) //a=4
}
传指针的好处:
- 能实现多个函数对一个对象进行操作
- 传指针比较轻量级(8bytes),只是传内存地址,可以用指针传递体积大的结构体,如果用参数值传递,每次copy上会花费相对比较多的系统开销(内存和时间)。
- Go语言中channel,slice,map是引用类型,可以直接传递,不用取地址之后再传递指针。(若函数需要改变slice的长度,仍需取地址传递指针)
5.函数作为值、类型
go语言中函数也是一种变量,可以通过type来定义,它的类型就是所有拥有相同的参数,相同的返回值的一种类型,可以把这个类型的函数当作值来传递。
type test func(int) bool
func isOdd(a int) bool{
if a%2==0{
return false
}
return true
}
func isEven(a int) bool{
if a%2==0{
return true
}
return false
}
//声明的函数类型作为一个参数
func filter(slice []int,f test)[]int{
var res []int
for _,num :=range slice{
if f(value){
res=append(res,value)
}
}
return res
}
func main(){
slice :=[]int{1,2,3,4,5}
odd :=filter(slice,isOdd) //函数作为值传递
even :=filter(slice,isEven) //函数作为值传递
}
6.函数判断是否为nil
当声明一个变量但还并未赋值时,golang会给予每个变量一个默认零值。
每种类型默认零值:
bool ---false
numbers ----0
string ------""
pointers-----nil
slices -----nil
maps----nil
channels----nil
functions---nil
interfaces---nil