提升 Go 编码效率,拒绝加班,真香

点击上方蓝色“飞雪无情”关注我的公众号,设个星标,第一时间看文章

在 Go 语言中,slice、map都是我们常用的基础类型,通过它们,我们可以很容易的使用数据。但是你有没有发现,为了对这两种数据进行处理,你不得不编写很多工具函数?

比如,从slice切片中查找一个元素的位置?这种查找又分为从前查找、从后查找。

又比如,获取map的所有keys?或者所有的value?

再比如,JS语言数组的map、reduce、filter函数,这在编程中非常好用,但是遗憾的是Go标准库没有提供。

这些例子,还有很多,而且都是我们编程中常用的工具函数,但是我们的 Go SDK 却没有。

但是我们又需要怎么办?一种办法,是我们自己编写一个工具包,用于给项目使用,但是这个工具包的维护,又是一个问题,需要人力。

第二种方式,就是用开源的库,经过充分的测试、验证,并且经常更新,所以可以保障。

因为我们遇到的是常见的问题,所以有人做了开源库,以供大家使用。这种工具库以 Go 1.18为分界线,Go 1.18之前有一款比较出名的是 go-funk。

很有意思的名字,Repo 地址是 https://github.com/thoas/go-funk。官方介绍就是一个Go语言工具库:

A modern Go utility library which provides helpers (map, find, contains, filter, ...)

它提供了很多好用的函数:Contains、Difference、IndexOf、LastIndexOf等等,具体更多的可以参考它的网站。

但是它有一个致命的问题,就是用到了反射。这也是没办法的事情,因为在Go 泛型没有支持之前,只能通过反射才能写出满足不同类型的函数。

举个IndexOf的例子,假如不用反射,要想支持更多的类型,就得定义很多相似名称的函数,如下所示。

func IndexOfBool(a []bool, x bool) int {




}


func IndexOfInt(a []int, x int) int {




}


func IndexOfInt32(a []int32, x int32) int {




}


func IndexOfInt64(a []int64, x int64) int {




}


func IndexOfUInt(a []uint, x uint) int {




}


func IndexOfUInt32(a []uint32, x uint32) int {




}


func IndexOfUInt64(a []uint64, x uint64) int {




}
func IndexOfFloat64(a []float64, x float64) int {


}
func IndexOfString(a []string, x string) int {


}

以上函数行不行?当然行,但是会写很多重复的代码,并且看着也怪怪的。

在Go语言的泛型支持之前,要解决这个问题,只能通过反射。

// IndexOf gets the index at which the first occurrence of value is found in array or return -1
// if the value cannot be found
func IndexOf(in interface{}, elem interface{}) int {
  inValue := reflect.ValueOf(in)


  elemValue := reflect.ValueOf(elem)


  inType := inValue.Type()


  if inType.Kind() == reflect.String {
    return strings.Index(inValue.String(), elemValue.String())
  }


  if inType.Kind() == reflect.Slice {
    equalTo := equal(elem)
    for i := 0; i < inValue.Len(); i++ {
      if equalTo(reflect.Value{}, inValue.Index(i)) {
        return i
      }
    }
  }


  return -1
}

泛型代码复杂,并且效率低。。。

那么Go 1.18之后已经支持了泛型,能不能用泛型来重写呢?

答案是:当然可以,并且已经有人这么做了。这个库就是 https://github.com/samber/lo ,也是我们今天要介绍的主角,开源3个月,6000多star!!!

它是基于Go泛型实现,没有用到反射,效率高,代码简洁。比如刚刚的IndexOf函数,在该库中是这么实现的:

// IndexOf returns the index at which the first occurrence of a value is found in an array or return -1
// if the value cannot be found.
func IndexOf[T comparable](collection []T, element T) int {
  for i, item := range collection {
    if item == element {
      return i
    }
  }


  return -1
}

只需要 T 被约束为comparable 的,就可以使用==符号进行比较了,整体代码非常简单,并且没有反射。

IndexOf只是lo几十个函数中的一个,这些函数基本上覆盖了slice、map、string等方方面面,涉及查找、比较大小、生成、map、reduce、过滤、填充、反转、分组等等,使用方法和示例,可以参考go doc文档。https://pkg.go.dev/github.com/samber/lo

Supported helpers for slices:

  • Filter

  • Map

  • FilterMap

  • FlatMap

  • Reduce

  • ForEach

  • Times

  • Uniq

  • UniqBy

  • GroupBy

  • Chunk

  • PartitionBy

  • Flatten

  • Shuffle

  • Reverse

  • Fill

  • Repeat

  • KeyBy

  • Drop

  • DropRight

  • DropWhile

  • DropRightWhile

  • Reject

  • Count

  • CountBy

Supported helpers for maps:

  • Keys

  • Values

  • PickBy

  • PickByKeys

  • PickByValues

  • OmitBy

  • OmitByKeys

  • OmitByValues

  • Entries

  • FromEntries

  • Invert

  • Assign (merge of maps)

  • MapKeys

  • MapValues

Supported math helpers:

  • Range / RangeFrom / RangeWithSteps

  • Clamp

  • SumBy

Supported helpers for strings:

  • Substring

  • RuneLength

Supported helpers for tuples:

  • T2 -> T9

  • Unpack2 -> Unpack9

  • Zip2 -> Zip9

  • Unzip2 -> Unzip9

Supported intersection helpers:

  • Contains

  • ContainsBy

  • Every

  • EveryBy

  • Some

  • SomeBy

  • None

  • NoneBy

  • Intersect

  • Difference

  • Union

Supported search helpers:

  • IndexOf

  • LastIndexOf

  • Find

  • FindIndexOf

  • FindLastIndexOf

  • Min

  • MinBy

  • Max

  • MaxBy

  • Last

  • Nth

  • Sample

  • Samples

Conditional helpers:

  • Ternary (1 line if/else statement)

  • If / ElseIf / Else

  • Switch / Case / Default

Type manipulation helpers:

  • ToPtr

  • ToSlicePtr

  • ToAnySlice

  • FromAnySlice

  • Empty

  • Coalesce

Concurrency helpers:

  • Attempt

  • AttemptWithDelay

  • Debounce

  • Async

Error handling:

  • Must

  • Try

  • TryCatch

  • TryWithErrorValue

  • TryCatchWithErrorValue

Constraints:

  • Clonable

随着Go语言泛型的完善,我相信这些工具函数,会成为Go标准库的一部分,被更多开发者使用。

现在,先把lo用起来吧~~~~

Go 团队在 GopherCon 2021 上的演讲:Go 1.18 泛型简介

一个简单的Golang实现Socket5 Proxy

Go 1.18 的工作区模式

2335caae2b906c44c2062613b81beba9.png

扫码关注

分享、点赞、在看就是最大的支持

猜你喜欢

转载自blog.csdn.net/flysnow_org/article/details/125270285
今日推荐