golang闭包函数

130 阅读1分钟

其实 Go 语言的赋值和函数传参规则很简单,除了闭包函数以引用的方式对外部变量访问之外,其它赋值和函数传参数都是以传值的方式处理 -- go语言高级编程

闭包函数:返回值是一个函数 golang闭包函数的记忆功能

package main

import (
   "fmt"
)

// Accumulate 提供一个值, 每次调用函数会指定对值进行累加
func Accumulate() func() int {
   var value int
   fmt.Println("value的地址 outer", &value)
   // 返回一个闭包
   return func() int {
      // 累加
      value++
      fmt.Println("value的地址 inner", &value)
      // 返回一个累加值
      return value
   }
}

func main() {
   // 创建一个累加器, 初始值为1
   accumulator := Accumulate()
   // 累加1并打印
   fmt.Println(accumulator())
   fmt.Println(accumulator())
}

执行结果:

  • value的地址 outer 0x140000ae018
  • value的地址 inner 0x140000ae018
  • 1
  • value的地址 inner 0x140000ae018
  • 2

闭包函数的使用:cron包


func TestChainSkipIfStillRunning(t *testing.T) {
   var buf syncWriter
   // 装饰者模式,在运行job之前运行一些东西
   cron := New(WithChain(SkipIfStillRunning(DiscardLogger)))
   cron.Start()
   defer cron.Stop()
   cron.AddFunc("@every 10s", func() {
      fmt.Println("hello world 1")
   })
   select {
   case <-time.After(2 * time.Minute):
      if !strings.Contains(buf.String(), "YOLO") {
         t.Error("expected a panic to be logged, got none")
      }
      return
   }
}
func SkipIfStillRunning(logger Logger) JobWrapper {
   return func(j Job) Job {
      var ch = make(chan struct{}, 1)
      ch <- struct{}{}
      return FuncJob(func() {
         select {
         case v := <-ch:
            defer func() { ch <- v }()
            j.Run()
         default:
            logger.Info("skip")
         }
      })
   }
}

如果当前正在运行,则skip跳过本次运行。使用的是信号量