golang函数式编程工具集插件库fp-go的使用

fp-go: Golang函数式编程工具集插件库使用指南

fp-go是一个基于Golang 1.18+泛型实现的函数式编程辅助工具库。

安装

需要Go 1.18+版本:

go get github.com/repeale/fp-go

主要特性

柯里化(Currying)

默认支持柯里化,数据最后传入:

func isPositive(x int) bool {
	return x > 0
}

func main() {
    filterPositive := fp.Filter(isPositive)
    numbers := []int{1, 2, 3, 4, 5}

    positives := filterPositive(numbers)
}

变体(Variations)

变体允许你在回调函数中获取不同的参数,只获取真正需要的参数。

默认变体

只获取当前元素:

fp.Map[int, string](func(x int) { ... })

带索引变体

获取当前元素和索引:

fp.MapWithIndex[int, string](func(x int, i int) { ... })

带切片变体

获取当前元素、索引和整个切片:

fp.MapWithSlice[int, string](func(x int, i int, xs: []int) { ... })

辅助函数

Every

判断数组中的所有元素是否满足指定条件。

变体: EveryWithIndexEveryWithSlice

fp.Every(func(x int) bool { return x > 0 })([]int{1, 2, 3})

// => true

Filter

返回数组中满足回调函数条件的元素。

变体: FilterWithIndexFilterWithSlice

fp.Filter(func(x int) bool { return x > 0 })([]int{-1, 2, -3, 4})

// => []int{2, 4}

Flat

将多维数组扁平化为一维数组:

fp.Flat([][]int{{1, 2}, {3, 4}})

// => []int{1, 2, 3, 4}

FlatMap

对数组每个元素调用回调函数,然后将结果扁平化。

变体: FlatMapWithIndexFlatMapWithSlice

fp.FlatMap(func(x int) []int { return []int{x, x} })([]int{1, 2})

// => []int{1, 1, 2, 2}

Map

对数组每个元素调用回调函数,返回结果数组。

变体: MapWithIndexMapWithSlice

fp.Map(func(x int64) string {
    return strconv.FormatInt(x, 10)
})([]int64{1, 2, 3})

// => []string{"1", "2", "3"}

Reduce

对数组每个元素调用回调函数,累积结果。

变体: ReduceWithIndexReduceWithSlice

fp.Reduce(func(acc int, curr int) int { return acc + curr }, 0)([]int{1, 2, 3})

// => 6

Some

判断数组中是否有元素满足回调函数条件。

变体: SomeWithIndexSomeWithSlice

fp.Some(func(x int) bool { return x < 0 })([]int{1, 2, 3})

// => false

Compose

从右到左组合函数。

变体: Compose2Compose16 表示要组合的函数数量。

func isPositive(x int) bool {
	return x > 0
}

func sumTwo(x int) int {
	return x + 2
}

Compose2(fp.Filter(isPositive), fp.Map(sumTwo))([]int{1, 2, 3, -1})

// => []int{3, 4, 5, 1}

Pipe

从左到右组合函数。

变体: Pipe2Pipe16 表示要组合的函数数量。

func isPositive(x int) bool {
	return x > 0
}

func sumTwo(x int) int {
	return x + 2
}

Pipe2(fp.Filter(isPositive), fp.Map(sumTwo))([]int{1, 2, 3, -1})

// => []int{3, 4, 5}

Curry

将多参数函数转换为单参数函数链。

变体: Curry2Curry16 表示要柯里化的参数数量。

curryedSum := Curry2(func(a int, b int) int { return a + b })
curryedSum(1)(2)

结构体

Option

表示可选值的封装,可用于可能返回或不返回有意义值的函数返回类型。

Option导出: Some, None, IsSome, IsNone, Chain, Exists, Flatten, FromError, FromErrorFn, FromPredicate, GetOrElse, Map, Match

Either

表示可以有两种可能类型的值。通常用Right表示成功值,Left表示失败值。

Either导出: Left, Right, IsLeft, IsRight, Exists, Flatten, FromError, FromErrorFn, FromOption, FromPredicate, GetOrElse, Map, MapLeft, Match


更多关于golang函数式编程工具集插件库fp-go的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang函数式编程工具集插件库fp-go的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


fp-go: Golang函数式编程工具集使用指南

fp-go 是一个为Go语言设计的函数式编程工具库,它提供了一系列高阶函数和实用工具,帮助开发者以更函数式的方式编写Go代码。

安装

go get github.com/repeale/fp-go

核心功能

1. 集合操作

fp-go 提供了类似JavaScript中Array.map/filter/reduce的功能:

import (
    "github.com/repeale/fp-go"
    "fmt"
)

func main() {
    numbers := []int{1, 2, 3, 4, 5}
    
    // Map: 对每个元素应用函数
    doubled := fp.Map(func(x int) int { return x * 2 })(numbers)
    fmt.Println(doubled) // [2 4 6 8 10]
    
    // Filter: 过滤元素
    evens := fp.Filter(func(x int) bool { return x%2 == 0 })(numbers)
    fmt.Println(evens) // [2 4]
    
    // Reduce: 聚合操作
    sum := fp.Reduce(func(acc, x int) int { return acc + x }, 0)(numbers)
    fmt.Println(sum) // 15
}

2. 函数组合

fp-go 支持函数组合,可以创建更复杂的函数:

import (
    "github.com/repeale/fp-go"
    "strings"
)

func main() {
    toUpper := func(s string) string { return strings.ToUpper(s) }
    addExclamation := func(s string) string { return s + "!" }
    
    // 组合函数
    shout := fp.Compose(addExclamation, toUpper)
    
    result := shout("hello")
    fmt.Println(result) // "HELLO!"
}

3. 柯里化(Currying)

fp-go 支持柯里化,可以将多参数函数转换为一系列单参数函数:

import "github.com/repeale/fp-go"

func main() {
    add := func(a, b int) int { return a + b }
    
    // 柯里化
    curriedAdd := fp.Curry2(add)
    
    addFive := curriedAdd(5)
    result := addFive(3)
    fmt.Println(result) // 8
}

4. 实用工具函数

fp-go 提供了一些实用工具函数:

import (
    "github.com/repeale/fp-go"
    "fmt"
)

func main() {
    // 恒等函数
    id := fp.Identity(42)
    fmt.Println(id) // 42
    
    // 常量函数
    alwaysFive := fp.Const(5)
    fmt.Println(alwaysFive()) // 5
    
    // 管道操作
    result := fp.Pipe(
        10,
        func(x int) int { return x * 2 },
        func(x int) int { return x + 3 },
    )
    fmt.Println(result) // 23
}

实际应用示例

数据处理管道

import (
    "github.com/repeale/fp-go"
    "fmt"
    "strings"
)

func main() {
    data := []string{"apple", "banana", "cherry", "date"}
    
    process := fp.Pipe(
        fp.Map(strings.ToUpper),
        fp.Filter(func(s string) bool { return len(s) > 5 }),
        fp.Map(func(s string) string { return "FRUIT: " + s }),
    )
    
    result := process(data)
    fmt.Println(result) // [FRUIT: BANANA FRUIT: CHERRY]
}

异步操作组合

import (
    "github.com/repeale/fp-go"
    "context"
    "fmt"
    "time"
)

func fetchUser(id int) func() string {
    return func() string {
        time.Sleep(100 * time.Millisecond)
        return fmt.Sprintf("User-%d", id)
    }
}

func fetchProfile(user string) func() string {
    return func() string {
        time.Sleep(100 * time.Millisecond)
        return fmt.Sprintf("Profile of %s", user)
    }
}

func main() {
    // 组合异步操作
    getUserProfile := fp.Compose(
        fetchProfile,
        fetchUser,
    )
    
    profile := getUserProfile(1)()
    fmt.Println(profile) // "Profile of User-1"
}

注意事项

  1. fp-go 的函数式风格与Go语言的惯用风格有所不同,使用时需权衡可读性
  2. 由于Go缺乏泛型(在1.18之前),fp-go 的类型安全性有限
  3. 性能方面,函数式操作可能比直接循环稍慢

fp-go 为Go开发者提供了函数式编程的便利,但建议根据项目需求适度使用,避免过度抽象影响代码可读性。

回到顶部