查看原文
其他

范型下,优雅的 Lodash 风

锐锐 GoCN 2022-09-09

推荐理由

go 语言比较崇尚简单,所以在内嵌包中没有提供过多帮助性的函数,尤其在范型出来前想要写一个简单的对 slice 和 map 间互相转化的方法可能就需要很多行代码,并且这样并不是很优雅。如今,go 范型已经得到官方的正式发布,samber/lo 又提供了优雅的 lodash 风格的工具函数,正是代码重构的好时机。

常见的使用场景

这里只是用 slice 和 map 两个常见结构举个栗子,lo 中支持超多的转化帮助函数供开发使用。

slice → map

在批量接口中,request 中携带 idList ,返回 map response
struct Request { IDList []int64}
struct Response { Metas map[int64]Meta}
// 用于模拟数据库查询数据struct Meta { ID int64 Name string}
func MGetMeta(req Request) Response{ result := make([]Meta,0, len(req.IDList)) // 执行 db query db.Raw("select * from meta where id in ?", req.IDList).Scan(&result) return Response{ Metas: MetaResult2Map(result), }}
// 旧代码: 针对不同的类型需要写不同的转化函数func MetaResult2Map(metas []Meta)map[int64]Meta{ res := make(map[int64]Meta) for _, m := range metas{ res[m.ID] = m } return res}
// 采用 lo:代码清晰,支持多种结构func MGetMeta(req Request) Response{ result := make([]Meta,0, len(req.IDList)) // 执行 db query db.Raw("select * from meta where id in ?", req.IDList).Scan(&result) return Response{ Metas: lo.KeyBy[int64,Meta](a, func(m Meta)int64{ return m.ID }), }}
map → slice
// 在对批量接口接口去重后,可能得到这样类型参数 map[int64]bool// 然后在db查询时其实只用map 的 key 的 slice// 旧代码实现func Int64MapKeys(m map[int64]interface{}) []int64{ res := make([]int64,0,len(m)) for k := range m{ res = append(res, k) } return res}
// 使用 lolo.Keys[int64,bool](map[int64]bool{1: true,2:true,3:true})
// 批量的聚合接口// 比如 定时任务中,扫表获取了一堆数据,分属于不同的业务方需要分别调用// 此时参数转化为 []T -> map[K][]T ,安装 T 中的某个字段进行分组func Group(m []T)map[K][]T{ res := make(map[K][]T) for _, v := range m{ if _, ok := res[v.Key];ok { res[v.Key] = append(res[v.Key],v) }else{ res[v.Key] = []T{v} } } return res}
// 使用 lolo.GroupBy([]Meta{{ID: 1,Name: "1"},{ID: 2, Name: "2"},{ID: 1,Name: "3"}}, func(t Meta) int64 { return t.ID})

总结

samber/lo 使用的开源 MIT 协议中提供了很多转化数据结构的方法,让日常开发更加方便优雅,而且其中的代码并不复杂,全部采用 go1.18 范型标注,对于初学者而言是个学习范型的好地方。笔者就是一边自己实现,一边对照 samber/lo 实现学习完这个库的。

参考

文档:

https://pkg.go.dev/github.com/samber/lo#KeyBy

github:

https://github.com/samber/lo


往期推荐



API设计中性能提升的10个建议


直播预约 | JetBrains 码上道:Go 语言的 netpoll 抽象与常见问题


sealer,“集群”版本的 Docker,交付复杂度的终结者

想要了解Go更多内容,欢迎扫描下方👇 关注 公众号,回复关键词 [实战群]  ,就有机会进群和我们进行交流~

分享、在看与点赞,至少我要拥有一个叭~

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存