Go每日一库之Pie :一个高性能、类型安全的slice操作库
2023-3-24 08:53:40 Author: Go语言中文网(查看原文) 阅读量:18 收藏

在Go语言中,对slice和map是我们最常用的数据结构。比如,计算两个切片的交集、差集;判断切片中的元素是否都满足某个条件的等。我推荐大家使用这个包:elliotchance/pie以下是该包的基本情况:

pie 小档案


star1.3 kused by--
contributors22作者Elliot Chance
功能简介该包封装了对切片和map的常用操作,能满足工作中的大部分需求。比如计算切片的交集、差集;对切片中元素按条件过滤的Filter函数;对切片中元素进行数据转换的Each、Map函数等。

同时具有高性能类型安全的特点。实现中对各函数的参数都做了类型的限制。比如Average函数就只能对整型和浮点型参数有效。

项目地址https://github.com/elliotchance/pie
相关知识切片的底层原理、切片性能

使用pie包的要求:

pie v2版本需要Go 1.18+。Go1.17及以下版本需要使用v1版本。

pie包的目标:

  • 类型安全:无论是在v1版本还是v2版本的泛型中,都对类型做了限制,所以不会遇到运行时类型错误。
  • 高性能:该库需要跟原生的Go实现一样快,否则该库封装就没有意义。
  • Nil安全:该库的所有函数都能接收nil参数,并将其视为空切片,而不会引起panic。
  • 对原切片无副作用:所有的函数对传入的切片参数都不会做修改。

使用示例

go 版本在1.18及以上,会使用pie/v2包,该包使用的是泛型。

package main

import (
    "fmt"
    "strings"

    "github.com/elliotchance/pie/v2"
)

func main() {

    name := pie.Of([]string{"Bob""Sally""John""Jane"}).
    FilterNot(func(name string) bool {
            return strings.HasPrefix(name, "J")
        }).
    Map(strings.ToUpper).
    Last()

    fmt.Println(name) // "SALLY"
}

go1.17及以下版本需要使用pie/v1包。因为在1.17之前go还不支持泛型,所以函数只能针对特定类型的切片。在该v1包中,pie实际上是定义了一组类型切片。比如,代表string切片的pie.Strings类型。代表float64切片的pie.Float64s类型。那么该版本在使用时需要先定义切片的类型。如下:

package main

import (
    "fmt"
    "strings"

    "github.com/elliotchance/pie/pie"
)

func main() {
    var names pie.Strings //看pie的源码Strings的底层类型是[]string
    names = []string{"Bob""Sally""John""Jane"}

    name := names.FilterNot(func(name string) bool {
                return strings.HasPrefix(name, "J")
            }).
        Map(strings.ToUpper).
        Last()

    fmt.Println(name) // "SALLY"
}

pie包支持的功能:

  • 切片中的元素是否全部或任意一个满足指定的条件。

    • All函数:判断切片中的元素是否都满足指定的条件。
    • Any函数:判断切片中的元素只要有1个满足指定条件即可。
  • 对切片元素进行排序功能。

    • AreSorted函数:判断切片是否是有序的
    • Sort函数:对切片元素进行排序。
    • SortStableUsing函数:使用指定的条件对切片进行排序,并且具有稳定性。
    • SortUsing函数
  • 对切片中的元素去重。

    • 判断切片中的元素是否不重复的AreUnique函数、去重函数Unique
  • 对切片进行前、后截取。

    • Bottom函数:取切片后n个元素
    • Top函数:取切片前n个元素
    • DropTop函数:丢掉切片的前n个元素,并返回剩余的元素切片
  • 两个或多个切片之间的集合运算

    • Diff函数:计算两个切片中的差集
    • Intersect函数:计算两个或多个切片的交集
  • 切片元素进行算数运算功能(只针对Integer和float类型的切片有效)。

    • Max函数:返回切片中的最大元素
    • Min函数:返回切片中的最小元素
    • Product函数:对切片所有元素进行乘积运算
    • Sum函数:对切片中所有元素进行求和运算
    • Average函数:求所有元素的平均值
  • 对切片中的元素进行数据转换功能:Each、Map、Filter、Flat、Reducer

  • 针对map的操作:

    • Keys函数:获取map的所有键
    • Values函数:获取map的所有值

更多、更详细的功能请参考pie包的源码。

总结

pie包几乎把slice经常用到的功能都做了封装,可谓是给开发者节省了大量时间。同时,v2包利用了泛型中的类型限制,保证了类型的安全。在性能方面,该包采用了很多策略:在已知切片长度的情况下尽可能给slice分配固定长度的内存,减少在使用append时内存申请的次数;使用切片截取的形式,避免内存再次分配。


推荐阅读

福利
我为大家整理了一份从入门到进阶的Go学习资料礼包,包含学习建议:入门看什么,进阶看什么。关注公众号 「polarisxu」,回复 ebook 获取;还可以回复「进群」,和数万 Gopher 交流学习。


文章来源: http://mp.weixin.qq.com/s?__biz=MzAxMTA4Njc0OQ==&mid=2651454203&idx=1&sn=6897f7ef36756827c500d8cd41ded580&chksm=80bb2409b7ccad1fac9576ec8eacbfa817bf478562bca705954ca33456e4968ecea65eab4374#rd
如有侵权请联系:admin#unsafe.sh