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

2024-01-03 10:34:03

在这里插入图片描述

参考地址

  • 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)
}


文章来源:https://blog.csdn.net/hmx224_2014/article/details/135356434
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。