闭包函数,Golang闭包的用法

嘿,你知道闭包是啥吗?就好比你的保温杯,一直记着你上次倒的咖啡温度。在 Go 语言中,闭包就像一个小助手,负责记住某个任务的状态。

比如,你有个任务是数羊(当然是为了入睡),闭包就是一个数羊的助手。他每数一只羊,就在心里记一下,下次再数的时候,继续从上次数到的羊数开始。这个助手就像是一个小精灵,一直默默地记录着你数了多少只羊。

go 复制代码
import "fmt"

func sheepCounter() func() int{
    count := 0
    return func() int{
        count++
        return count
    }
}

func main(){
    countSheep := sheepCounter()
    
    fmt.Println(countSheep())	// 输出 1
    fmt.Println(countSheep())	// 输出 2
    fmt.Println(countSheep())	// 输出 3
}

下面会详细解释为什么会输出 1 2 3

闭包是函数的返回值,也可以一种函数值,它引用了函数体外的变量。在 Go 中,函数可以是闭包,这意味着它可以访问并保留在其作用域之外定义的变量。这种特性使得函数可以作为函数参数传递,用于构建灵活的代码结构。

基本概念

  1. 函数是第一类公民:在 Go 中,函数是第一类公民,可以像其他值一样传递和使用。这使得函数可以作为参数传递给其他函数,也可以作为函数的返回值。
  2. 捕获外部变量:闭包可以访问并捕获在其作用域之外定义的变量。这些变量的值在闭包内部被保留,即使外部函数执行完毕,闭包仍然可以使用这些变量。

示例

1、计数器
go 复制代码
import "fmt"

func sheepCounter() func() int{
    count := 0
    return func() int{
        count++
        return count
    }
}

func main(){
    countSheep := sheepCounter()
    
    fmt.Println(countSheep())	// 输出 1
    fmt.Println(countSheep())	// 输出 2
    fmt.Println(countSheep())	// 输出 3
}
  • 外部函数sheepCounter的定义
go 复制代码
func sheepCounter() func() int{

sheepCounter 函数返回一个函数,该函数的签名是 func() int,即它没有参数,返回一个整数。

  • 内部函数的定义
go 复制代码
count := 0
return func() int{
    count++
    return count
}

sheepCounter 函数内部定义了一个局部变量 count,用于存储计数器的当前值。

返回的是一个匿名函数(闭包),该函数不接受参数,但在每次调用时递增 count 变量的值,并返回递增后的值。

  • 计数器的使用
go 复制代码
countSheep := sheepCounter()
fmt.Println(countSheep()) // 输出: 1
fmt.Println(countSheep()) // 输出: 2
fmt.Println(countSheep()) // 输出: 3

main 函数中,创建了一个计数器 countSheep,它实际上是调用 sheepCounter 函数后返回的闭包。

每次调用 countSheep(),闭包会递增 count 变量的值,并返回递增后的计数器值。

由于闭包中捕获了外部函数sheepCounter中的count变量,该变量的生命周期得以延续,不受外部函数执行完毕的影响。这样,每次调用闭包时,都会在原有计数器值得基础上递增,实现了一个简单的计数器功能。

2、函数工厂
go 复制代码
package main

import "fmt"

func multiplier(factor int) func(int) int {
	return func(x int) int {
		return x * factor
	}
}

func main(){
    double := multiplier(2)
    triple := multiplier(3)
    
    fmt.Println(double(5)) // 输出: 10
    fmt.Println(triple(5)) // 输出: 15
}

这个例子中,multiplier 函数返回一个闭包,用于创建乘法器。通过创建不同的闭包,可以轻松地生成具有不同乘数的乘法器函数。

以上就是关于Go语言闭包的所有内容,如果对你有帮助,点赞收藏加关注~

tips:

如何加快对语言的理解?多敲案例,案例简单,也许手脑一起动~

Java选手看一下这个案例,或许会眼前一亮~

java 复制代码
public class Main {
    public static void main(String[] args) {
        Counter counter = new Counter(0);
        System.out.println(counter.countAdd());
        System.out.println(counter.countAdd());
        System.out.println(counter.countAdd());

        Counter co1 = new Counter(2);
        Counter co2 = new Counter(3);
        System.out.println(co1.multiplier(5));
        System.out.println(co2.multiplier(5));
    }
    public static class Counter{
        private Integer count;

        public Integer countAdd(){
            return count++;
        }

        public Integer multiplier(Integer x){
            return count * x;
        }

        public Counter() {
        }

        public Counter(Integer count) {
            this.count = count;
        }

        public Integer getCount() {
            return count;
        }

        public void setCount(Integer count) {
            this.count = count;
        }
    }
}
相关推荐
IT_陈寒8 分钟前
Redis的DEL命令竟然没删掉数据?我踩的这个坑你得知道
前端·人工智能·后端
用户9385156350710 分钟前
Docker + Nginx + Node.js:从“我的电脑能跑,你的电脑跑不了”到一键部署
后端·nginx·docker
陆枫Larry12 分钟前
两步验证(2FA )到底是什么?
后端
JavaGuide16 分钟前
我用 Claude Code/ZCode+GLM-5.3 从零做了一款 Agent 游戏!
前端·后端
程序员清风28 分钟前
专业再升级!程序员专属显示器明基RD280UG上手实测!
java·后端·面试
刘立军1 小时前
RESTful 与契约优先:规范接口定义,统一接口设计范式
后端·架构·ai编程
JavaGuide2 小时前
GitHub 4.5 万+ Star!GitNexus 把代码仓库变成了 Claude Code / Codex 能查询的知识图谱
后端·ai编程
子兮曰2 小时前
DeepSeek Harness 架构深潜:一个把 Agent 运行时做成纯插件树的开源 Harness
前端·后端·deepseek
子兮曰3 小时前
AI Agent 完整入门指南:从 LLM 到生产落地的 30+ 个核心概念
前端·后端·agent
渔夫正在掘金4 小时前
Cordis 插件热插拔能力深度解析
后端·node.js