Go语言中的Slice链式操作方法是什么

您所在的位置:网站首页 韩国makemodole Go语言中的Slice链式操作方法是什么

Go语言中的Slice链式操作方法是什么

2023-04-09 10:40| 来源: 网络整理| 查看: 265

Go语言中的Slice链式操作方法是什么 发布时间:2023-04-07 17:36:40 来源:亿速云 阅读:77 作者:iii 栏目:开发技术

今天小编给大家分享一下Go语言中的Slice链式操作方法是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

示例

首先模拟一个业务场景,有订单、产品、自定义订单三个结构体,订单中包含多个产品:

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 


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3