Go 语言 func函数 | 青训营笔记

157 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天,本次是对于go语言中func函数的学习。

Go 语言 func函数

函数是结构化编程中最小的模块单元,将复杂的算法过程分解为若干个小任务(代码块),使程序的结构性更清晰。

在Go语言中,当函数执行到代码块最后一行 "}"之前或者return语句时会退出结束,其中return可以带有0个或多个参数,return语句可以用来结束for死循环或者结束一个Go协程(Goroutine)

定义语法:

func 函数名(参数列表)(返回值列表){
​
•   //函数体
​
}
func funcNameinput1 type1input2 type2)(out1 type1out2 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