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

参考地址

函数式编程(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)
}
相关推荐
eqwaak012 分钟前
科技信息差(9.13)
大数据·开发语言·人工智能·华为·语言模型
郝学胜-神的一滴16 分钟前
深入探索 Python 元组:从基础到高级应用
运维·服务器·开发语言·python·程序人生
一只乔哇噻19 分钟前
java后端工程师进修ing(研一版‖day44)
java·开发语言·学习·算法
Ares-Wang38 分钟前
Vue3》》eslint Prettier husky
开发语言·javascript·ecmascript
canonical_entropy1 小时前
不同的工作需要不同人格的AI大模型?
人工智能·后端·ai编程
EveryPossible1 小时前
静态箭头连线
开发语言·javascript·ecmascript
NiKo_W1 小时前
Git 版本回退与撤销修改
开发语言·git·安全
IT_陈寒1 小时前
Vite 5.0 终极优化指南:7个配置技巧让你的构建速度提升200%
前端·人工智能·后端
listhi5201 小时前
Map对象在JavaScript循环中的使用
开发语言·前端·javascript
小熊学Java1 小时前
基于 Spring Boot+Vue 的高校竞赛管理平台
vue.js·spring boot·后端