Go语言函数

Go语言函数1.简介函数:为完成某一功能的程序指令(语句)的集合在Go中,函数分为自定义函数、系统函数2.基本语法func函数名(形参列表)(返回值列表){函数体return返回值列表}3.递归函数体内调用自己packagemainimport"fmt"f

大家好,欢迎来到IT知识分享网。

1.简介

  • 函数:为完成某一功能的程序指令(语句)的集合
  • Go中,函数分为自定义函数、系统函数

2.基本语法

func 函数名(形参列表) (返回值列表) {
    函数体
    return 返回值列表
}

3.递归

  • 函数体内调用自己
package main

import "fmt"

func test(n int) {
    if n > 2 {
        n--
        test(n)
    }
    fmt.Println("n = ", n)
}

func main() {
    test(4)
}
  • 执行一个函数时,就创建一个新的受保护的独立空间
  • 函数的局部变量是独立的,不会相互影响
  • 递归必须向退出递归的条件逼近,否则就会出现无限递归
  • 当一个函数执行完毕,或者遇到return,就会返回,遵守谁调用就将结果返回给谁。

Go语言函数

4.递归练习

  • 1.求第N个斐波那契数列对应的值
package main

import "fmt"

func feb(n int) int {
    if n <= 2 {
        return 1
    }
    return test(n-1) + test(n-2)
}

func main() {
    result := feb(6)
    fmt.Println(result)
}
  • 2.已知函数f(1) = 3f(n) = 2*f(n-1) + 1,求f(n)的值
package main

import "fmt"

func test(n int) int {
    if n == 1 {
        return 3
    }
    return 2*test(n-1) + 1
}

func main() {
    result := test(6)
    fmt.Println(result)
}

  • 3.有一堆桃子,猴子第一天吃了其中的一半,并在多吃了一个!以后每天猴子都吃其中的一半,然后再多吃一个。当到第十天准备吃时,发现只剩了1个桃子问题:最初总共多少个桃子

Go语言函数

  • 从上图可以看出其通项公式为:(1 + f(n+1))* 2n代表天数
package main

import "fmt"

func getPeach(n int) int {
    if n == 10 {
        return 1
    }
    return (1 + getPeach(n+1)) * 2
}

func main() {
    result := getPeach(1)
    fmt.Println(result)
}

5.函数使用注意细节

  • 1.函数的形参列表和返回值列表都可以是多个

  • 2.形参列表和返回值列表都可以是值类型或引用类型

  • 3.函数命名遵循标识符命名规则,首字母不能是数字,首字母如果是大写,则可以被其他文件或包调用,否则只能在当前文件被调用

  • 4.函数的变量是局部的,函数外不生效

  • 5.基本类型和数组默认都是值传递,即进行值拷贝,在函数内修改,不会影响到原来的值

  • 6.如果希望函数内的变量能修改函数外的变量,可以传递变量的地址&,函数内以指针方式操做变量

  • 7.Go函数不支持重载(即一个包下不允许存在同名的函数)

  • 8.在Go语言中,函数也是一种数据类型,可以赋值给一个变量,则该变量就是一个函数类型的变量,通过该变量可以对函数进行调用

  • 9.函数既然是一种数据类型,因此在Go语言中,函数可以作为形参,并且调用

    package main
    
    import "fmt"
    
    func test(myFunc func(int, int) int, num1, num2 int) int {
        return myFunc(num1, num2)
    }
    
    func getSum(a, b int) int {
        return a + b
    }
    func main() {
        resp := test(getSum, 1, 2)
        fmt.Println(resp)
    }
    
  • 10.为了简化数据类型定义,Go语言支持自定义数据类型

    • 基本语法:type myInt int,myInt就可以当作int类型来使用,但不完全一致,不能将一个myInt类型的值直接赋值给int类型的变量,需要使用int()来强转一下。
    • 也可以使用type来定义一个函数类型
    package main
    
    import "fmt"
    
    type myFuncType func(int, int) int
    
    func test(myFunc myFuncType, num1, num2 int) int {
        return myFunc(num1, num2)
    }
    
    func getSum(a, b int) int {
        return a + b
    }
    
    func main() {
        resp := test(getSum, 1, 2)
        fmt.Println(resp)
    }
    
  • 11.支持对函数返回值命名

    package main
    
    import "fmt"
    
    type myFuncType func(int, int) int
    
    func test(myFunc myFuncType, num1, num2 int) int {
        return myFunc(num1, num2)
    }
    
    // 将函数返回值重命名为sum
    func getSum(a, b int) (sum int) {
        sum = a + b
        return
    }
    
    func main() {
        resp := test(getSum, 1, 2)
        fmt.Println(resp)
    }
    
  • 12.使用_来忽略返回值

  • 13.Go支持可变参数参数名 ...,必须放在参数最后位置

    package main
    
    import "fmt"
    
    func getSum(args ...int) int {
        sum := 0
        for i := 0; i < len(args); i++ {
            sum += args[i]
        }
        return sum
    }
    func main() {
        resp := getSum(1, 2, 3)
        fmt.Println(resp)
    }
    

6.init函数

  • 每个源文件都可以包含一个init函数,该函数会在main函数前执行,被Go运行框架调用。
  • 通常在init函数中完成初始化工作,每个文件都可以有一个init函数
    package main
    
    import "fmt"
    
    func init() {
        fmt.Println("init函数自动执行")
    }
    
    func main() {
        fmt.Println("开始执行主函数")
    }
    
  • 如果一个文件中同时包含全局变量init函数main函数,则执行顺序为:全局变量 > init > main
    package main
    
    import "fmt"
    
    var money = test()
    
    func test() int {
        fmt.Println("test()")
        return 100
    }
    
    func init() {
        fmt.Println("init函数自动执行")
    }
    
    func main() {
        fmt.Println("开始执行主函数...money=", money)
    }
    
    // test()
    // init函数自动执行
    // 开始执行主函数...money= 100
    

7.匿名函数

  • Go支持匿名函数,如果我们某个函数只希望使用一次,可以考虑使用匿名函数,匿名函数可以实现多次调用
  • 示例一:在定义时就调用
    package main
    
    import "fmt"
    
    func main() {
        res := func(n1, n2 int) int {
            return n1 + n2
        }(10, 20)
        fmt.Println("result =", res)
    }
    
  • 示例二:将匿名函数赋值给一个变量(函数变量),再通过该变量来调用匿名函数
    package main
    
    import "fmt"
    
    func main() {
        sum := func(n1, n2 int) int {
            return n1 + n2
        }
    
        res := sum(10, 20)
        fmt.Println("result =", res)
    }
    
  • 示例三:全匿名函数,将函数赋值给一个全局变量,就成为一个全局函数,可以在程序有效
    package main
    
    import "fmt"
    
    var multi = func(n1, n2 int) int {
        return n1 * n2
    }
    
    func main() {
        res := multi(10, 20)
        fmt.Println("result =", res)
    }
    

8.闭包

  • 闭包就是一个函数与其相关的引用环境组合的一个整体

  • 闭包必须满足三个条件:
    1、必须有一个内嵌函数
    2、内嵌函数必须引用外部函数中的变量
    3、外部函数返回值必须是内嵌函数

  • 闭包可以使得变量常驻内存

    package main
    
    import "fmt"
    
    func Closure() func(int) int {
        var n1 = 10
        return func(n2 int) int {
            n1 = n1 + n2
            return n1
    
            // return n1 + n2  // 这样的结果完全不一样, n1 = n1 + n2会修改局部变量n1的值,如果直接返回n1 + n2,则不会修改局部变量n1的值
        }
    }
    
    func main() {
        res := Closure()
        fmt.Println("result =", res(30)) // 40
        fmt.Println("result =", res(31)) // 71
    }
    
  • nodejs

    function closure() { 
        var a = 10; 
        function inner(b) {
            a = a + b;  
            return a
        } 
        return inner;
    }
    var func = closure();
    console.log(func(30));  // 40
    console.log(func(31));  // 71
    
  • python

    # 变量 a 对于 inner来说是外部变量,因此不能直接进行修改
    def closure():
        a = 10
        def inner(b):
            a = a + b
            return a
        return inner
    
    # UnboundLocalError: local variable 'a' referenced before assignment
    
    # 但对于inner来说是可以直接使用的
    def closure():
        a = 10
        def inner(b):
            return a + b
        return inner
    
    # 必须使用 nonlocal 来修改变量a的作用域,从而对其进行操做
    def closure():
        a = 10
        def inner(b):
            nonlocal a
            a = a + b
            return a
        return inner
    
    func = closure()
    print(func(30))  # 40
    print(func(31))  # 71
    
  • 案例:使用闭包方式,实现检查文件后缀名是否为.jpg,如果不是,则内部实现拼接.jpg,否则直接返回

    package main
    
    import (
    	"fmt"
    	"strings"
    )
    
    func Closure(endFix string) func(string) string {
        return func(name string) string {
            if strings.HasSuffix(name, endFix) {
                return name
            }
            return name + endFix
        }
    }
    
    func main() {
        res := Closure(".jpg")
        fmt.Println("result =", res("aaa.jpg"))
        fmt.Println("result =", res("bbb"))
    }
    

9.函数参数传递

  • 值类型:基本数据类型:int系列、float系列、bool、string、数组、结构体
  • 引用类型:指针、slice切片、map、管道chan、interface等

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/30437.html

(0)
上一篇 2023-11-19 14:45
下一篇 2023-11-21 18:45

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信