[每周一更]-(第52期):Go的函数式编程

在这里插入图片描述

参考地址

  • https://hedzr.com/golang/fp/golang-functional-programming-in-brief/
  • https://silverrainz.me/blog/funtional-programming-in-go-generics.html
  • https://zhuanlan.zhihu.com/p/436468481

函数式编程(Functional Programming / FP)作为一种编程范式,具有无状态、无副作用、并发友好、抽象程度高等优点。

Go语言并不是一门纯粹的函数式编程语言,但它支持一些函数式编程的特性和思想。函数式编程是一种编程范式,
其核心理念是将计算视为函数应用的组合,强调使用纯函数、不可变性和避免副作用。

声明式编程:函数式编程倾向于使用声明式风格,将关注点放在"做什么"而不是"如何做"上。通过使用函数组合、管道操作符等,可以在Go中实现声明式的风格,使代码更易读、简洁和可维护。

  • 高阶函数:Go语言中函数是一等公民,可以作为参数传递给其他函数,也可以作为返回值。这使得我们可以编写高阶函数,即接受其他函数作为参数或返回函数的函数。
  • 闭包:Go语言支持闭包,可以在函数内部定义函数,并访问外部函数的变量。闭包在函数式编程中常用于创建不可变的函数,或者捕获一些状态并将其封装在函数中。
  • 函数组合:通过将多个函数组合在一起形成新的函数,可以实现函数的复用和组合。可以使用函数的嵌套调用、函数参数传递和返回函数等方式来实现函数组合。
  • 纯函数:纯函数是指没有副作用的函数,即函数的返回值仅由输入决定,不依赖于外部状态。在Go中,可以通过避免修改函数外部的变量和数据,以及避免使用全局状态,来编写纯函数。
  • 不可变性:尽量避免在函数中修改传入的参数或外部变量,而是创建新的数据结构或使用函数返回新的结果。这样可以减少副作用,增加代码的可读性和可维护性。
  • 函数链式调用:通过返回对象本身或其他具有相同方法的对象,可以实现函数链式调用的风格。这在Go中常用于构建流畅的API接口或操作符。

高阶函数示例:

定义一个高阶函数mapInts,它接受一个整数切片和一个函数作为参数,并将该函数应用于切片中的每个元素。

func mapInts(nums []int, f func(int) int) []int {
    result := make([]int, len(nums))
    for i, num := range nums {
        result[i] = f(num)
    }
    return result
}

func main() {
    nums := []int{1, 2, 3, 4, 5}
    doubled := mapInts(nums, func(x int) int {
        return x * 2
    })
    fmt.Println(doubled) // Output: [2 4 6 8 10]
}

闭包示例:

使用闭包创建一个计数器函数,每次调用计数器函数都会增加计数器的值。

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

func main() {
    counter := newCounter()
    fmt.Println(counter()) // Output: 1
    fmt.Println(counter()) // Output: 2
    fmt.Println(counter()) // Output: 3
}

函数组合示例:

定义两个函数addOne和double,然后将它们组合在一起形成一个新的函数addOneAndDouble。

func addOne(x int) int {
    return x + 1
}

func double(x int) int {
    return x * 2
}

func compose(f func(int) int, g func(int) int) func(int) int {
    return func(x int) int {
    return f(g(x))
    }
}

func main() {
    addOneAndDouble := compose(addOne, double)
    result := addOneAndDouble(2)
    fmt.Println(result) // Output: 5
}

斐波那契数列

想要直接调用 printContentFile () 自动生成斐波那契数,就必须实现 read 接口,定义一个 type:函数。使其实现 Reader 接口。

//函数实现接口
//定义一个函数,使用type修饰。可以实现接口,也就是说只要是被type修饰的东西都可以实现接口。

type IntGen func() int

//实现read接口
func (g IntGen) Read(p []byte) (n int, err error) {
    next := g()

    if next > 10000 { //这里因为不设置退出会一直打印下去,所以做了限制
    return 0, io.EOF
    }
    s := fmt.Sprintf("%d\n", next)
    return strings.NewReader(s).Read(p)
}

func printContentFile(reader io.Reader) {
    scanner := bufio.NewScanner(reader)
    for scanner.Scan() { //
        println(scanner.Text())
    }
}

func fibonacci() IntGen {
    a := 0
    b := 1
    return func() int {
        a, b = b, a+b
        return a
    }
}

func main(){
    fun := fibonacci()
    printContentFile(fun)
}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/287197.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

解决实用编程题目:单词拆分和分割等和子集--动态规划方式深度呈现

139. 单词拆分 题目描述 给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。 注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。 示例 1: 输入: s "lee…

OpenCV图像处理——C++实现亚像素尺寸标定板边缘轮廓提取

前言 标定模板(Calibration Target)在机器视觉、图像测量、摄影测量以及三维重建等应用中起着重要的作用。它被用于校正相机的畸变,确定物理尺寸和像素之间的换算关系,并建立相机成像的几何模型。通过使用相机拍摄带有固定间距图…

JavaScript中的数据缓存与内存泄露:解密前端性能优化与代码健康

​🌈个人主页:前端青山 🔥系列专栏:JavaScript篇 🔖人终将被年少不可得之物困其一生 依旧青山,本期给大家带来JavaScript篇专栏内容:JavaScript-数据缓存与内存泄露 目录 说说你对事件循环的理解 一、是什么 二、宏…

Linux操作系统基础(7):Linux的文件路径

1. Linux文件路径的介绍 在Linux系统中,文件路径是用来定位文件或目录在文件系统中位置的一种表示方法,它能够帮助用户快速、准确地定位文件或目录,并进行相应的操作。 文件路径可以分为 绝对路径 和 相对路径 两种类型: 绝对路…

H266/VVC熵编码技术概述

熵编码 熵编码: 是指按信息熵原理进行的无损编码方式,无损熵编码也是有损视频编码中的一个关键模块,它处于视频压缩系统的最末端。熵编码把一列系用来表示视频序列的元素符号转变为一个用来传输或存储的压缩码流,输入的符号可能包…

提高开发效率的必备!超实用的VSCode插件推荐

前言 作为一个前端程序猿,我经常使用 VSCode 代码编辑器,但是每个开发者都有自己独特的工作风格和偏好。为了满足不同开发者的需求,VSCode 提供了丰富的插件生态系统。在本文中,我将为大家推荐一些强大的 VSCode 插件,…

Linux学习之系统编程3(进程及wait函数)

写在前面: 我的Linux的学习之路非常坎坷。第一次学习Linux是在大一下的开学没多久,结果因为不会安装VMware就无疾而终了,可以说是没开始就失败了。第二次学习Linux是在大一下快放暑假(那个时候刚刚过完考试周)&#xf…

SpringFrameWork

SpringFrameWork简介 介绍springFrameWork框架 Spring Framework是一个为企业级应用程序开发提供全面基础设施支持的开源框架,通过集成IoC、DI和AOP等技术,使得应用程序的开发更加灵活、可维护和可扩展。Spring MVC、SpringBoot、Spring Cloud、Spring D…

java实现大文件分片上传

背景: 公司后台管理系统有个需求,需要上传体积比较大的文件:500M-1024M;此时普通的文件上传显然有些吃力了,加上我司服务器配置本就不高,带宽也不大,所以必须考虑多线程异步上传来提…

数据结构与算法python版本之线性结构之队列Quene

什么是队列? 队列是一种有次序的数据集合,其特征是:新数据项的添加总发生在一端(通常称为“尾rear”端),而现存数据项的移除总发生在另一端(通常称为“首front”端);当数…

缓存数据一致性策略如何分类?

一、概述 数据库与缓存数据一致性问题,一直以来都是大家比较关注的问题。针对一致性的解决方案也是非常多,以下主要针对方案的梳理与分类: 数据库数据与缓存数据一致性的方案,可以从不同的角度来分类,比如&#xff1…

稳定币记录

稳定币: 稳定币(Stablecoin)是一种加密货币,其设计目的是维持相对稳定的价值,通常与某种法定货币(如美元、欧元)或其他资产(如黄金)挂钩。稳定币通过将加密货币与相应的…

Flink-【时间语义、窗口、水位线】

1. 时间语义 1.1 事件时间:数据产生的事件(机器时间); 1.2 处理时间:数据处理的时间(系统时间)。 🌰:可乐 可乐的生产日期 事件时间(可乐产生的时间&…

计算机毕业设计 SpringBoot的停车场管理系统 Javaweb项目 Java实战项目 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…

逻辑回归算法到底能做什么

逻辑回归(Logistic Regression)是一种广义的线性回归分析模型,常用于数据挖掘、疾病自动诊断、经济预测等领域。它根据给定的自变量数据集来估计事件的发生概率。变量的范围在0和1之间,通常用于二分类问题,最终输出的预…

Opencv(C++)学习之cv::calcHist 任意bin数量进行直方图计算

**背景:**当前网上常见的直方图使用方法都是默认使用256的范围,而对于使用特定范围的直方图方法讲的不够清楚。仔细研究后总结如下: 1、常见使用方法,直接对灰度图按256个Bin进行计算。 Mat mHistUn; int channels[1] { 0 }; {…

键盘数字键打不出来怎么解锁?收藏好这4个简单方法!

“我在使用电脑进行办公时,突然发现我电脑键盘的数字键无法输入,这该怎么办呢?我应该如何解锁呢?请给我出出主意吧!” 在日常使用电脑时,很多用户都需要使用键盘输入文字。但有时候部分用户也会遇到键盘数字…

你知道vue中key的原理吗?说说你对它的理解

一、Key是什么 开始之前&#xff0c;我们先还原两个实际工作场景 当我们在使用v-for时&#xff0c;需要给单元加上key <ul><li v-for"item in items" :key"item.id">...</li> </ul>用new Date()生成的时间戳作为key&#xff0c…

Docker 网络管理

一、Docker网络简介 Docker网络是容器化应用程序的重要组成部分&#xff0c;它使得容器之间可以互相通信和连接&#xff0c;同时也提供了容器与外部环境之间的隔离和连接。 二、Docker网络网络模式 Docker 提供了多种网络模式&#xff0c;可以通过docker network ls 命令查看…

springboot实现ChatGPT式调用(一次调用,持续返回)

下边实现了一个持续返回100以内随机数的接口&#xff0c;在接口超时之前会每隔1秒返回一个随机数 GetMapping(value "/getRandomNum", produces MediaType.TEXT_EVENT_STREAM_VALUE) public SseEmitter getRandomNum() {SseEmitter emitter new SseEmitter();Th…