【Go基础】函数

本是古典 何须时尚 2022-09-03 14:24 238阅读 0赞

函数

  • 函数

    • 基本介绍
    • 匿名函数
    • 函数闭包
    • 相关资料

基本介绍

基础格式形如:

func function_name ([parameter list]) [return_types] {

​ 函数体

}

  • func:function的缩写,是定义函数的关键字。
  • function_name:函数名。
  • [parameter_lists]:函数列表,可以有0个或多个。
  • [return_types]:返回值类型,可以有0个或多个返回值。
  • 示例一:基操

    import “fmt”

    func main() {

    1. var v = add(1, 2)
    2. fmt.Println("v = ", v) // 输出:a2 = 10

    }

    func add(a int, b int) int {

    1. return a + b

    }

  • 示例二:如果相邻的参数类型相同,则可以采用简便写法

    import (

    1. "fmt"
    2. "strconv"

    )

    func main() {

    1. fmt.Println(hello(1, 2, "Justry", "Deng")) // 输出:3JustryDeng

    }

    func hello(a, b int, c, d string) string {

    1. // strconv.Itoa的作用是:将int转换为tring
    2. return strconv.Itoa(a+b) + c + d

    }

  • 示例三:多返回值

    import (

    1. "fmt"

    )

    func main() {

    1. v1, v2 := hello(0, 0)
    2. fmt.Println(v1, "\t", v2) // 输出:100 -100

    }

    func hello(a, b int) (int, int) {

    1. return1 := a + 100
    2. return2 := b - 100
    3. return return1, return2

    }

  • 示例四:无返回值

    import (

    1. "fmt"

    )

    func main() {

    1. hello("邓沙利文")

    }

    func hello(name string) {

    1. fmt.Println("hello " + name) // 输出:hello 邓沙利文

    }

  • 示例五:形参传递变量的地址(,在方法内部可修改外部变量的值)

    提示:对照组是没使用地址变量前的效果,实验组是使用地址变量后的效果

    • 对照组

      1. import (
      2. "fmt"
      3. )
      4. func main() {
      5. a := 1
      6. add(a)
      7. fmt.Println("调用add后,值为", a) // 输出:调用add后,值为 1
      8. }
      9. func add(v int) {
      10. v++
      11. fmt.Println("add方法内部,值为", v) // 输出:add方法内部,值为 2
      12. }
    • 实验组

      1. import (
      2. "fmt"
      3. )
      4. /** * 提示:值变量前加上&, 即代表值变量的地址 * 地址变量前加上*, 即代表地址变量的地址值 */
      5. func main() {
      6. a := 1
      7. add(&a)
      8. fmt.Println("调用add后,值为", a) // 输出:调用add后,值为 2
      9. }
      10. func add(v *int) {
      11. *v++
      12. fmt.Println("add方法内部,值为", *v) // 输出:add方法内部,值为 2
      13. }

注:在值变量前加上&,可以得到值变量的地址;在地址变量前加上*,可代表内存单元,即:指向该地址的值变量的值

匿名函数

匿名函数即没有函数名字的函数

  • 示例一:基操

    import (

    1. "fmt"

    )

    func main() {

    1. a := func(v int) int {
    2. return v + 1
    3. }(99)
    4. fmt.Println("a = ", a) // 输出:a = 100

    }

提示:匿名函数体后,带小括号才代表该匿名函数被调用

  • 示例二:匿名函数作为参数

    import (

    1. "fmt"

    )

    func main() {

    1. a, b := 300, 500
    2. fmt.Println("a + b = ", addOrSub(a, b, add)) // 输出:a + b = 800
    3. fmt.Println("a - b = ", addOrSub(a, b, sub)) // 输出:a - b = -200

    }

    func add(a, b int) int {

    1. return a + b

    }

    func sub(a, b int) int {

    1. return a - b

    }

    /* 其中变量f的类型是函数 func(v1, v2 int) int, 即:所有满足func(v1, v2 int) int格式要求的函数,都可以作为该处的参数 */
    func addOrSub(a, b int, f func(v1, v2 int) int) int {

    1. return f(a, b)

    }

函数闭包

所谓闭包就是在函数内部,可以读取父函数的变量

  • 代码示例:

    func getSequence() func() int {

    1. i := 0
    2. return func() int {
    3. i++
    4. return i
    5. }

    }

  • 说明:getSequence()中的内部结构,i在该函数内部定义,属于局部变量,但是在返回的匿名函数中对这个i进行了引用(闭包),并且把这个i进行了返回。每当getSequence()被调用时实际得到的是以func() int为原型的匿名函数,由于该匿名函数对i的引用一直存在,因此本来是临时变量的i在getSequence()返回后并不会被释放,内存分析如图:
    在这里插入图片描述

  • 这个getSequence函数的作用很有意思,在通过调用getSequence得到的匿名函数每次调用时,都会促使i的值自增,这样就得到了类似数据库中的自增序列那样的功能,示例:

    1. import (
    2. "fmt"
    3. )
    4. func main() {
    5. nextnumber := getSequence()
    6. fmt.Println(nextnumber()) // 输出:1
    7. fmt.Println(nextnumber()) // 输出:2
    8. fmt.Println(nextnumber()) // 输出:3
    9. }
    10. func getSequence() func() int {
    11. i := 0
    12. return func() int {
    13. i++
    14. return i
    15. }
    16. }
  • 加深理解:如果再用一个f := getSequence(),fnextnumber交替使用,彼此会互相影响吗?答案是不会。虽然getSequence()被调用时i是不释放的,但是不同的getSequence()调用时对应的i的内存地址是不同的,也就是说2此调用会产生2个独立的i,不会彼此影响,内存分析如图:
    在这里插入图片描述
  • 用代码验证一下:

    1. import (
    2. "fmt"
    3. )
    4. func main() {
    5. nextnumber := getSequence()
    6. fmt.Println(nextnumber()) // 输出:1
    7. fmt.Println(nextnumber()) // 输出:2
    8. fmt.Println(nextnumber()) // 输出:3
    9. f := getSequence()
    10. fmt.Println(f()) // 输出:1
    11. fmt.Println(f()) // 输出:2
    12. fmt.Println(f()) // 输出:3
    13. }
    14. func getSequence() func() int {
    15. i := 0
    16. return func() int {
    17. i++
    18. return i
    19. }
    20. }

^_^ 整理自《Go语言区块链应用开发从入门到精通》高野 编著

^_^ 本文已经被收录进《程序员成长笔记》 ,笔者JustryDeng

发表评论

表情:
评论列表 (有 0 条评论,238人围观)

还没有评论,来说两句吧...

相关阅读