• 闭包


    基本介绍: 闭包就是一个函数和与其相关的引用环境组合的一个整体(实体)

    案例演示:

    package main
    import (
      "fmt"
    )

    //累加器
    func AddUpper() func (int) int {
      var n int = 10
      return func (x int) int {
        n = n + x
        return n
      }
    }

    func main() {
      //使用上面的代码
      f := AddUpper()
      fmt.Println(f(1))   //11
      fmt.Println(f(2))   //13
      fmt.Println(f(3))   //16

    }

    对上面代码的说明和总结:

    1)AddUpper 是一个函数,返回的数据类型是func (int) int。

    2)闭包的说明:

      var n int = 10
      return func (x int) int {
        n = n + x
        return n
      }

    返回的是一个匿名函数,但是这个匿名函数引用到函数外的n, 所以这个匿名函数就和n形成一个整体,构成闭包。


    3)可以这样理解:闭包是类,函数是操作,n是字段。函数和它使用到的n构成闭包。

    4)当我们反复的调用 f 函数时,因为 n 是初始化一次,因此每调用一次就进行累计。

    5)我们要搞清楚闭包的关键,就是要分析出返回的函数它使用(引用)到哪些变量,因为函数和它引用到的变量共同构成闭包。

    6)对上面的代码的一个修改,加深对闭包的理解

    package main
    import (
    "fmt"
    )

    //累加器
    func AddUpper() func (int) int {
      var n int = 10
      var str = "hello"
      return func (x int) int {
        n = n + x
        str += string(36)
        fmt.Println("str = ", str)   //1.str="hello$" 2.str="hello$$" 3.str="hello$$$"
        return n
      }
    }

    func main() {
      //使用前面的代码
      f := AddUpper()
      fmt.Println(f(1))   //11
      fmt.Println(f(2))   //13
      fmt.Println(f(3))   //16
    }

    闭包的最佳实践:

    请编写一个程序,具体要求如下:

    1)编写一个函数 makeSuffix(suffix string) 可以接收一个文件后缀名(比如.jpg),并返回一个闭包

    2)调用闭包,可以传入一个文件名,如果该文件名没有指定的后缀(比如.jpg),则返回 文件名.jpg,如果已经有.jpg后缀,则返回源文件名。

    3)要求使用闭包的方式完成

    4)strings.HasSuffix

    函数HasSuffix:

      func HasSuffix(s, suffix string) bool
      判断s是否有后缀字符串suffix。


    代码:

    package main
    import (
    "fmt"
    "strings"
    )

    func makeSuffix(suffix string) func (string) string {
      return func (name string) string {
        //如果 name 没有指定后缀,则加上,否则就返回原来的名字
        if !strings.HasSuffix(name, suffix) {
          return name + suffix
        }
        return name
      }

    }

    func main() {

      //返回一个闭包
      f := makeSuffix(".jpg") //如果使用闭包完成,好处是只需要传入一次后缀
      //测试makeSuffix 的使用
      fmt.Println("文件名处理后=", f("winter"))
      fmt.Println("文件名处理后=", f("bird.jpg"))
    }


    代码说明:

    1)返回的匿名函数和 makeSuffix(suffix string) 里面的 suffix 变量 和返回的函数组合成一个闭包,因为返回的函数引用到suffix这个变量

    2)我们体会一下闭包的好处,如果使用传统的方法,也可以轻松实现这个功能,但是传统方法需要每次都传入 后缀名,比如.jpg,而闭包因为可以保留上次引用的某个值,所以我们传入一次就可以反复使用。

    传统方法的例子:

    func makeSuffix2(suffix string, name string) string {

      //如果 name 没有指定后缀,则加上,否则就返回原来的名字
      if !strings.HasSuffix(name, suffix) {
        return name + suffix
      }
      return name
    }

    func main() {

      fmt.Println("文件名处理后=", makeSuffix2("jpg","winter"))    //每次都得传后缀名
      fmt.Println("文件名处理后=", makeSuffix2("jpg","bird.jpg"))
    }

  • 相关阅读:
    Openjudge-NOI题库-简单算术表达式求值
    洛谷-求同构数的个数-NOIP2013提高组复赛
    洛谷-拼数-NOIP1998提高组复赛
    洛谷-统计数字-NOIP2007提高组复赛
    洛谷-谁拿了最多奖学金-NOIP2005提高组复赛
    Openjudge-NOI题库-字符串移位包含问题
    洛谷-乘积最大-NOIP2000提高组复赛
    NOIP2015-普及组复赛-第一题-金币
    Tyvj-超级书架
    Openjudge-NOI题库-出书最多
  • 原文地址:https://www.cnblogs.com/green-frog-2019/p/11355085.html
Copyright © 2020-2023  润新知