详解Go语言中的Slice链式操作-环球快资讯
2023-04-08 06:09:59 来源: 脚本之家
【资料图】
目录
示例原理实现示例
首先模拟一个业务场景,有订单、产品、自定义订单三个结构体,订单中包含多个产品:
type Order struct { Id string Products []Product } type Product struct { Id string Price int } type CustomOrder struct { Id string }
初始化模拟数据:
var orders = []Order{ { Id: "o1", Products: []Product{ { Id: "p1", Price: 1, }, { Id: "p2", Price: 2, }, }, }, { Id: "o2", Products: []Product{ { Id: "p3", Price: 3, }, { Id: "p4", Price: 4, }, }, }, }
接下来对订单列表做各种操作:
// 过滤Id为o2的订单 func TestFilter(t *testing.T) { res := Lists[Order](orders).Filter(func(o any) bool { return o.(Order).Id == "o2" }).Collect() t.Log(res) // [{o2 [{p3 3} {p4 4}]}] } // 将订单列表映射为自定义订单列表 func TestMap(t *testing.T) { res := Lists[CustomOrder](orders).Map(func(o any) any { return CustomOrder{ Id: "custom-" + o.(Order).Id, } }).Collect() t.Log(res) // [{custom-o1} {custom-o2}] } // 将每个订单里的产品展开,并映射为自定义订单 func TestFlatAndMap(t *testing.T) { res := Lists[CustomOrder](orders). Flat(func(o any) []any { return Lists[any](o.(Order).Products).ToList() }). Map(func(p any) any { return CustomOrder{ Id: "ProductId-" + p.(Product).Id, } }).Collect() t.Log(res) // [{ProductId-p1} {ProductId-p2} {ProductId-p3} {ProductId-p4}] } // 找到所有订单产品中价格最贵的那个产品 func TestMax(t *testing.T) { res, found := Lists[Product](orders). Flat(func(o any) []any { return Lists[any](o.(Order).Products).ToList() }). Max(func(i, j any) bool { return i.(Product).Price > j.(Product).Price }) t.Log(found, res) // true {p4 4} }
原理
type List[T any] struct { list []any }
将 go 中的原生切片包装成 List[T]
结构体,特别说明其中的泛型 T
是最终结果的元素类型,并不是原始传入切片的类型。
这样设计是因为 go 只能在构造结构体时指定泛型,因此将 List[T]
的泛型指定为最终结果的元素类型,就可以在操作完成后调用 Collect()
方法,得到最终的 T
类型切片,方便后面的业务逻辑使用。
因为 go 不支持在接受者函数中定义泛型,因此所有操作函数的参数和返回值类型只能定义为any
,然后在函数体内转换为业务结构体使用,例如上面的 i.(Product).Price
。
此后将每一种操作,例如Filter、Map、Flat等,都返回List[T]
结构体,就可以实现链式操作。
实现
type List[T any] struct { list []any } func Lists[T any](items any) *List[T] { rv := reflect.ValueOf(items) if rv.Kind() != reflect.Slice { panic(fmt.Sprintf("not supported type: %v, please use slice instead", rv.Kind())) } l := rv.Len() s := make([]any, 0, l) for i := 0; i < l; i++ { s = append(s, rv.Index(i).Interface()) } return &List[T]{ list: s, } } func (s *List[T]) Filter(fn func(any) bool) *List[T] { l := make([]any, 0) for _, e := range s.list { if fn(e) { l = append(l, e) } } s.list = l return s } func (s *List[T]) Map(fn func(any) any) *List[T] { l := make([]any, 0) for _, element := range s.list { l = append(l, fn(element)) } return &List[T]{ list: l, } } func (s *List[T]) Flat(fn func(any) []any) *List[T] { l := make([]any, 0) for _, element := range s.list { l = append(l, fn(element)...) } return &List[T]{ list: l, } } func (s *List[T]) Sort(fn func(i, j any) bool) *List[T] { if len(s.list) <= 0 { return s } sort.SliceStable(s.list, func(i, j int) bool { return fn(s.list[i], s.list[j]) }) return s } func (s *List[T]) Max(fn func(i, j any) bool) (T, bool) { return s.Sort(fn).FindFirst() } func (s *List[T]) FindFirst() (T, bool) { if len(s.list) <= 0 { var nonsense T return nonsense, false } return s.list[0].(T), true } func (s *List[T]) ToList() []any { return s.list } func (s *List[T]) Collect() []T { t := make([]T, 0) for _, a := range s.list { t = append(t, a.(T)) } return t }
到此这篇关于详解Go语言中的Slice链式操作的文章就介绍到这了,更多相关Go Slice链式操作内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
标签:
为您推荐
精彩放送
热门文章
-
四川天府银行董事长、行长同时换帅,能否一改往日业绩颓势?
-
高质量发展担当,宁波银行“韧性”释放
-
先诊疗后付费,在这家医院成为了现实|天天新消息
-
天下车智|电驱版轩逸中国问世,日系家轿还回得去昔日荣光吗?
-
员工被强制加班怒怼领导
-
当前速讯:“高德+口碑”挑起阿里本地生活的大梁
-
东方创新医疗股票型基金发售 掘金创新药投资“富矿”|环球今头条
-
【世界快播报】货拉拉的盈利焦虑:既赚商户的钱,也赚司机的钱
-
创新赋能 砥砺深耕 阳光财险荣获《中国银行保险报》三项大奖_环球快报
-
雍禾医疗,静待自己的“周期共振”_环球新视野
-
世界滚动:长虹美菱2022年年报:三箭齐发 营利双增
-
库迪咖啡全面提价?客服回应:4月起部分地区产品确已涨价
精彩图片
热文
-
五年来 中法贸易总额从600亿美元升至800亿美元
-
联合国粮农组织:全球食品价格指数连续12个月下跌_天天讯息
-
俄媒:一名曾在美被关押超10年的俄公民将给特朗普发“监狱生存指南”-焦点快看
-
北京心学力教育科技有限公司荣获斯贝瑞奖“2023年度最具增长力品牌”
-
今头条!2023郴州市教育系统事业单位人才引进专区
-
兰州市各县区开展文明交通劝导志愿服务
-
环球快看点丨兰州市西固区整治大街小巷 倡导文明新风
-
全球报道:【中央媒体看甘肃】2023年甘肃省体育统考将对考生进行兴奋剂抽检
-
全球微动态丨甘肃省拟选拔580名领军人才
-
“调剂服务系统”今日开通—— 一图了解2023年硕士生招生调剂流程
-
房贷提前还款利息怎么算?还款怎么操作?_全球速讯
-
观天下!提前还贷款要收违约金吗?提前还款对信用有影响吗?
-
手里有钱了建议提前还房贷吗?还清房贷还需要办什么手续?
-
四川天府银行董事长、行长同时换帅,能否一改往日业绩颓势?
-
00后美女,给你20万,你愿意去猪场养猪吗?毕业两年半能存20万|天天最新
-
补栏热情“降温” 仔猪价格“见顶”回落,未来有跌破500元/头的可能!
-
豆粕期货、现货价格大幅上涨,部分地区涨幅200元左右
-
市场一片阴云笼罩,玉米何时才能走出阴霾?
-
重点聚焦!猪价不断探底,节后猪价底线是多少?14元/公斤上下
-
卢拉提议,未卷入俄乌冲突的国家成立“和平小组”,提到中国和巴西
-
美媒:乌军作战计划遭泄露,美国军方紧急调查?
-
卢拉批美国欧盟:他们在俄乌冲突初期未寻求谈判,而是“加入”战争
-
刑事案成催化剂?民调:特朗普有望于共和党总统初选出线|最资讯
-
联合国儿基会呼吁为土耳其250万受地震影响的儿童提供援助
-
鱼头汤(鱼头怎么做好吃)
-
山丹:大棚育苗忙 乡村产业旺_全球新要闻
-
金塔:温室大棚“绿”意浓 种出幸福好“钱”景 天天观点
-
玉门:羊产业“链”出致富路 热点在线
-
成县:春日乡村美 民富产业兴 独家
-
世界信息:成县:3.3万亩蒜苔迎来“丰收季”
-
还房贷提前还款需要什么手续?房贷的申请条件有哪些?
-
房贷提前还10万扣了一千多利息怎么算?提前还房贷的好处?
-
房贷30年提前还什么时间最合适?提前还款怎么操作?-动态
-
数密通:护航数据要素流通 释放数字经济红利|最资讯
-
一艘载有339名非法移民的救援船抵达意大利南部港口_环球新消息
-
外交部:美方应深刻反省,停止针对全球的网络窃密行径 全球微速讯
-
加拿大将向日本部署军机以支持美国对朝鲜制裁,外交部回应-今日看点
-
联合国:刚果(金)超30人遭极端武装杀害 世界速看料
-
当前快讯:黎巴嫩防长:黎南部局势升级已对当地构成直接威胁
-
浙江财经大学团队获得首届中国研究生金融科技创新大赛一等奖
-
全球球精选!长安画派美术作品在西安展出
-
房贷几年后可以提前还款?提前还款流程是什么?
-
提前还房贷有违约金怎么办?房贷有哪些还款方式?
-
全球短讯!提前还房贷划得来吗?提前还款银行拖延怎么办?
-
家用美容仪行业乱象跟踪——策划“伪科学”收割“智商税”
-
2×660MW!国能福州热电二期超超临界热电联产工程五通一平施工项目招标 世界焦点
-
一周国际动物疫情动态-405期
-
减少200万头!傲农率先下调今年出栏目标,正虹卖房“回血”,新希望、新五丰下修业绩...全国母猪加速淘汰?-全球播报
-
美媒:美国今年龙卷风相关死亡人数已接近年均总数
-
美国纽约一监狱突发火灾致20伤 起火正值州议员访问之际