开放的编程资料库

当前位置:我爱分享网 > Go教程 > 正文

Go关闭

Go闭包教程展示了如何在Golang中使用闭包。

Go函数是一等公民。函数可以分配给变量、存储在集合中、动态创建和删除,或作为参数传递。

嵌套函数,也称为内部函数,是在另一个函数中定义的函数。匿名函数是未绑定到标识符的函数定义。匿名函数通常是传递给高阶函数的参数

$ go version
go version go1.18.1 linux/amd64

我们使用Go版本1.18。

去闭包

Go闭包是一个匿名嵌套函数,它保留对在闭包主体外定义的变量的绑定。

闭包可以拥有自己独特的状态。当我们创建函数的新实例时,状态就会变得孤立。

package main

import "fmt"

func main() {

     sum := func(a, b, c int) int {
          return a + b + c
     }(3, 5, 7)

     fmt.Println("5+3+7 =", sum)
}

我们创建了一个添加三个值的匿名函数。我们在函数定义后立即将三个参数传递给该函数。

Go闭包简单例子

在下面的例子中,我们定义了一个简单的闭包。

package main

import "fmt"

func intSeq() func() int {

    i := 0
    return func() int {
        i++
        return i
    }
}

func main() {

    nextInt := intSeq()

    fmt.Println(nextInt())
    fmt.Println(nextInt())
    fmt.Println(nextInt())
    fmt.Println(nextInt())

    nextInt2 := intSeq()
    fmt.Println(nextInt2())
}

我们有intSeq函数,它生成一个整数序列。它返回一个递增i变量的闭包。

func intSeq() func() int {

intSeq是一个函数,它返回一个重新运行整数的函数。

func intSeq() func() int {

    i := 0
    return func() int {
        i++
        return i
    }
}

函数中定义的变量具有局部函数作用域。但是,在这种情况下,即使在intSeq函数返回后,闭包也绑定到i变量。

nextInt := intSeq()

我们调用intSeq函数。它返回一个函数,该函数将增加一个计数器。返回的函数关闭变量i以形成闭包。闭包绑定到nextInt名称。

fmt.Println(nextInt())
fmt.Println(nextInt())
fmt.Println(nextInt())
fmt.Println(nextInt())

我们多次调用闭包。

nextInt2 := intSeq()
fmt.Println(nextInt2())

intSeq函数的下一次调用返回一个新的闭包。这个新的闭包有自己独特的状态。

$ go run closure.go
1
2
3
4
1

Go闭包斐波那契示例

斐波那契数列是一个值序列,每个数字都是前面两个数字的总和,从0和1开始。序列的开头是:0、1、1、2、3、5、8、13,21,34,55,89,144…

package main

import "fmt"

func fibonacci() func() int {

     a := 0
     b := 1

     return func() int {

          a, b = b, a+b
          return b-a
     }
}

func main() {

     f := fibonacci()

     for i := 0; i < 10; i++ {

          fmt.Println(f())
     }
}

这是使用闭包实现的斐波那契数列。如果fibonacci函数未保留ab的值,则计算将无法进行。

$ go run fibonacci.go
0
1
1
2
3
5
8
13
21
34

Go闭包中间件

中间件是在向服务器发出请求的生命周期中执行的函数。中间件通常用于日志记录、错误处理或数据压缩。

在Go中,中间件通常是在闭包的帮助下创建的。

package main

import (
     "fmt"
     "log"
     "net/http"
     "time"
)

func main() {

     http.HandleFunc("/now", logDuration(getTime))
     fmt.Println("Server started at port 8080")
     log.Fatal(http.ListenAndServe(":8080", nil))
}

func logDuration(f func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {

     return func(w http.ResponseWriter, r *http.Request) {

          start := time.Now()
          f(w, r)
          end := time.Now()
          fmt.Println("The request took", end.Sub(start))
     }
}

func getTime(w http.ResponseWriter, r *http.Request) {

     now := time.Now()
     _, err := fmt.Fprintf(w, "%s", now)

     if err != nil {
          log.Fatal(err)
     }
}

我们有一个简单的HTTP服务器,它用当前日期时间响应/now

http.HandleFunc("/now", logDuration(getTime))

在Go中,函数可以作为参数传递给其他函数。我们将logDuration函数包装在getTime函数之上。

func logDuration(f func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {

     return func(w http.ResponseWriter, r *http.Request) {

          start := time.Now()
          f(w, r)
          end := time.Now()
          fmt.Println("The request took", end.Sub(start))
     }
}

logDuration函数返回一个获取当前时间的闭包,调用原始函数,获取结束时间,并打印出请求的持续时间。闭包对于处理函数内部实际发生的事情是不可知的。

在本教程中,我们使用了Golang中的闭包。

列出所有Go教程。

未经允许不得转载:我爱分享网 » Go关闭

感觉很棒!可以赞赏支持我哟~

赞(0) 打赏