美文网首页
go语言基础之函数

go语言基础之函数

作者: Fizz翊 | 来源:发表于2018-11-19 13:26 被阅读3次

    欢迎来我的个人博客:fizzyi

    自定义函数

    1.定义格式

    函数构成代码执行的逻辑结构。在Go语言中,函数的基本组成为:关键字func,函数名,参数列表,返回值,函数体和返回语句。

    Go语言函数定义格式如下:

    
    func FuncName(/*参数列表*/)(o1 type1,o2 type2/*返回类型*/) 
    
    //函数体 
    
    return v1,v2//返回多个值 
    
    

    返回类型说明:

    1. 上面返回值声明了两个变量名o1和o2(命名返回参数),这个不是必须,可以只有类型没有变量名

    2. 如果只有一个返回值且不声明返回值变量,那么你可以省略,包括返回值的括号

    3. 如果没有返回值,那么就直接省略最后的返回信息。

    4. 如果有返回值,那么必须在函数的内部添加return语句

    2.函数定义

    2.1无参数无返回值

    
    func Test(){ //无参数无返回值函数定义 
    
    fmt.Println('this is a test func') 
    
    } 
    
    func main(){ 
    
    Test() //无参数无返回值函数调用 
    
    } 
    
    

    2.2有参数无返回值

    2.2.1普通参数列表

    
    func Test01(v1 int ,v2 int){ //方式一 
    
    fmt.Printf("v1 = %d,v2 = %d\n",v1,v2) 
    
    } 
    
    func Test02(v1,v2 int){ //方式2,v1,v2都是Int类型 
    
    fmt.Printf("v1 = %d ,v2 =%d\n",v1,v2) 
    
    } 
    
    func main(){ 
    
    Test01(10,20) 
    
    Test02(11,22) 
    
    } 
    
    

    2.2.2不定参数列表

    不定参数是指函数传入的参数个数为不定数量,为了做到这点,首先需要将函数定义为接受不定参数类型

    
    //形如...type格式的类型只能作为函数的参数类型存在,并且必须是最后一个参数 
    
    func Test(args ...int){ 
    
    for _,n := range args{ //遍历参数列表 
    
    fmt.Println(n) 
    
    } 
    
    } 
    
    func main(){ 
    
    //函数调用,可传0到多个参数 
    
    Test() 
    
    Test(1,2,3,4) 
    
    } 
    
    

    2.3无参数有返回值

    有返回值的函数,必须有明确的终止语句,否则会引发编译错误

    2.3.1一个返回值

    
    func Test01() int { //方式1 
    
    return 250 
    
    } 
    
    func Test02()(value int ){ //方式2,给返回值命名 
    
    value =250 
    
    return value 
    
    } 
    
    

    2.3.2多个返回值

    
    func Test01()(int ,string){ //方式1 
    
    return 250,"sb" 
    
    } 
    
    func Test02()(a int ,str string){ //方式2,给返回值命名 
    
    a = 250 
    
    str = "sb" 
    
    return 
    
    } 
    
    

    2.3.3有参数有返回值

    
    \#求两个数的最小值和最大值 
    
    func MinAndMax(num1 int,num2 int)(min int ,max int){ 
    
    if num1 > num2{ 
    
    min = num2 
    
    max = num1 
    
    } else{ 
    
    min = num1 
    
    max = num2 
    
    } 
    
    return 
    
    } 
    
    func main(){ 
    
    min,max = MinAndMax(10,20) 
    
    fmt.Printf("min=%d,max=%d",min,max) 
    
    } 
    
    

    2.4递归函数

    递归指函数可以直接或间接的调用自身

    
    //通过循环实现1+2+3....+100 
    
    func Test1() int{ 
    
    i := 1 
    
    sum := 0 
    
    for i = 1;i<=100;i++{ 
    
    sum +=1 
    
    } 
    
    return sum 
    
    } 
    
    //通过递归实现1+2+3...+100 
    
    func Test02(num int) int { 
    
    if num == 1{ 
    
    return 1 
    
    } 
    
    return num + Test02(num-1) 
    
    } 
    
    func main(){ 
    
    fmt.Println(Test1()) 
    
    fmt.Println(Test2(100)) 
    
    } 
    
    

    3.函数类型

    在Go语言中,函数也是一种数据类型,我们可以通过type来定义它,它的类型就是所有拥有相同的参数,相同的返回值的一种类型。

    
    type FuncType func(int,int)int //声明一个函数类型,func后面没有函数名 
    
    func Cale(a,b int,f FuncType)(result int){ //函数中哟哟一个参数类型为函数类型 f 
    
    result = f(a,b) 
    
    return 
    
    } 
    
    func Add(a,b int)int{ 
    
    return a+b 
    
    } 
    
    func Minus(a,b int)int{ 
    
    return a-b 
    
    } 
    
    func mian(){ 
    
    result := Cale(1,2,Add) #计算加法 
    
    var f FuncType = Minus 
    
    fmt.Println("result = ",f(10,2)) 
    
    } 
    
    

    4.匿名函数与闭包

    所谓闭包就是一个函数“捕获”了和它在同一作用域的其他常量和变量。这就意味着当闭包被调用的时候,不管在程序什么地方调用,闭包能够使用这些常量或者常量,它不关心中文系为捕获了的变量和常量是否已经超出了作用域,所以只要闭包还在使用它,这些常量就还会存在。

    在Go语言里,所有的匿名函数都是闭包。

    
    func main(){ 
    
    i := 0 
    
    str := "mike" 
    
    //方式一 
    
    f1 := func(){ //匿名函数,无函数名无参数无返回值 
    
    //引用到函数外的变量 
    
    fmt.Printf("方式1:i=%d,str = %s\n",i,str) 
    
    } 
    
    f1() //函数调用 相当于给这个函数命名为f1 
    
    //方式一的另一种方式 声明了一个FuncType函数类型,然后f2的类型设为functype类型并且赋值为f1 
    
    type FuncType func() //声明为函数类型,无参无返回值 
    
    var f2 FuncType = f1 
    
    f2() 调用 
    
    } 
    
    //方式2 初始化的同时赋值 
    
    var f3 FuncType = func(){ 
    
    fmt.Printf("方式2:i = %d,str = %s\n",i,str) 
    
    } 
    
    f3() //函数调用 
    
    //方式3 
    
    func(){ //匿名函数,无参数无返回值 
    
    fmt.Printf("方式3:i = %d ,str = %s\n",i,str) 
    
    }() //写完后在后面直接写(),直接执行该匿名函数 
    
    //方式4 匿名函数,有参数有返回值 
    
    v := func(a,b,int)(result int){ 
    
    result = a + b 
    
    return 
    
    }(1,1) //传入1,1 直接调用此匿名函数并且传入参数 
    
    

    闭包捕获外部变量特点:

    
    func main(){ 
    
    i := 10 
    
    str := "mike" 
    
    func(){ 
    
    i = 100 
    
    str = "go" 
    
    //内部: i = 100,str = go 
    
    }() //直接调用此匿名函数 
    
    //外部: i = 100, str = go 
    
    } 
    
    

    函数返回值为匿名函数

    
    //squares返回一个匿名函数,func() int 
    
    //该匿名函数每次被滴啊用时都会返回下一个数的平方 
    
    func squares() func() int{ 
    
    var x int 
    
    return func() int{ //匿名函数 
    
    x++ //捕获外部变量 
    
    return x*x 
    
    } 
    
    } 
    
    func main(){ 
    
    f := squares() 
    
    fmt.Println(f()) // 1 
    
    fmt.Println(f()) // 4 
    
    fmt.Println(f()) // 9 
    
    fmt.Println(f()) // 16 
    
    } 
    
    

    squares返回另一个类型为func()int类型的函数。对squares的一次调用会生成一个局部变量x并返回一个匿名函数。

    变量的声明周期不由它的作用域决定:squares返回后,变量x仍然隐式的存在于f中。

    5 延迟调用defer

    5.1 defer作用

    关键字defer用于延迟一个函数或者方法(或者当前创建的匿名函数)的执行。注意,defer语句中只能出现在函数或者方法的内部。

    func mian(){
        fmt.Println("this is a test")
        defer fmt.Println("this is a defer") //main结束前调用
    }
    /*
        运行结果:
        this is a test
        this is a defer
    */
    

    defer语句经常被用于处理成对的操作,如打开,关闭,连接,断开连接,加锁,释放锁。通过defer机制,不论函数逻辑多复杂都能保证在任何执行路径下,资源被释放。释放资源的defer应该直接跟在请求资源的语句后面。

    5.2 多个defer执行顺序

    如果一个函数中有个defer语句,它们会以后进先出的顺序执行。即使出错,这些调用依旧会被执行。

    func test(x int){
        fmt.Println(100 / x) //x为0时,产生异常
    }
    
    func main(){
        defer fmt.Println("aaaaaa")
        defer fmt.Println("bbbbbb")
        
        defer test(0)
        
        defer fmt.Println("ccccccc")
    }
    /*
    运行结果:
        cccccc
        bbbbbb
        aaaaaa
        panic: runtime error :integer divide by zero
    */
    

    5.3defer和匿名函数结合使用

    func main(){
        a,b := 10,20
        defer func(x int){ //a以值传递的方式传给x
            fmt.Println("defer:"x,b) //b 闭包使用
        }(a)
        
        a += 10
        b += 100
        
        fmt.Printf("a = %d,b = %d\n",a,b)
        /*
            运行结果:
            a = 20,b = 120
            defet:10, 120
        */
    }
    

    相关文章

      网友评论

          本文标题:go语言基础之函数

          本文链接:https://www.haomeiwen.com/subject/pvgofqtx.html