自学内容网 自学内容网

go 切片进行链式操作并支持泛型

背景:

      由于团队不是专业级别的go开发人员,主开发还是java,用惯了java的lambda表达式特别是流式操作, 所以在用go语言时,发现切片处理起来比较麻烦,看看能不能支持类似流式操作,我这边就研究了下这块业务,发现是可以实现的,同时要支持所有类型,所以必然要支持泛型才可以,背景介绍完,开始正题:

定义泛型的类型形参列表:

// SliceAble
//
//@Description: 泛型,如果需要支持其他类型,请自行添加
//@Author  zhaosy
//@date  2024-07-12 17:07:22
type SliceAble interface {
Person | string | int
}

定义切片类型


// Slice
// 定义新切片类型
type Slice[T SliceAble] []T

// NewSlice [T SliceAble]
//
//@Author  zhaosy
//@Description: newSlice
//@date  2024-07-13 13:22:23
func NewSlice[T SliceAble](arr []T) Slice[T] {
     //这里为了不影响原始切片数据,所以进行copy,如果不关心可以删除直接返回arr即可
copyArr := make([]T, len(arr), len(arr))
copy(copyArr, arr)
return copyArr
}

// Filter
//
//@Author  zhaosy
//@Description: 过滤,demo:
//people := []lang.Person{
//{"Alice", 45},
//{"Elizabeth", 75},
//{"Alice", 25},
//{"Bob", 30},
//{"Alice", 2},
//{"Bob", 4},
//{"Colin", 5},
//{"Elizabeth", 34},
//}
//
//p := lang.NewSlice(people).Filter(func(i lang.Person) bool {
//return i.Age > 30
//})
//
//fmt.Println(p) //[{Alice 45} {Elizabeth 75} {Elizabeth 34}]
//@date  2024-07-13 11:48:46
func (s Slice[T]) Filter(f func(T) bool) Slice[T] {
var temp Slice[T]
for _, v := range s {
b := f(v)
if b {
temp = append(temp, v)
}

}
return temp
}

// Sort
//
//@Author  zhaosy
//@Description: 排序:
//排序规则根据函数放回的bool类型进行排序,demo:
//people := []lang.Person{
//{"Alice", 45},
//{"Elizabeth", 75},
//{"Alice", 25},
//{"Bob", 30},
//{"Alice", 2},
//{"Bob", 4},
//{"Colin", 5},
//{"Elizabeth", 34},
//}
//lang.NewSlice(people).Sort(func(s lang.Slice[lang.Person], i, j int) bool {
//return s[i].Age > s[j].Age
//})
//fmt.Println(people) //结果:[{Elizabeth 75} {Alice 45} {Elizabeth 34} {Bob 30} {Alice 25} {Colin 5} {Bob 4} {Alice 2}]
//
//@date  2024-07-13 11:41:14
func (s Slice[T]) Sort(f func(s Slice[T], i, j int) bool) Slice[T] {
sort.SliceStable(s, func(i, j int) bool {
return f(s, i, j)
})
return s
}

// Append
//
//@Author  zhaosy
//@Description: 追加元素;采用go 底层切片append方式
//@date  2024-07-13 13:13:09
func (s Slice[T]) Append(newObj T) Slice[T] {
s = append(s, newObj)
return s
}

// OnePointerObj
//
//@Author  zhaosy
//@Description: 返回单条数据实例,是指针类型,且判断是否为空
//@date  2024-07-13 13:13:41
func (s Slice[T]) OnePointerObj() *T {
if len(s) == 0 {
return nil
}
return &s[0]
}


// OnePointerObj
//
//@Author  zhaosy
//@Description: 返回json字符串,如果为空,直接返回空字符串
//@date  2024-07-13 13:47:41
func (s Slice[T]) ToJsonStr() string {
b, err := json.Marshal(s)
if err != nil {
fmt.Println(err)
return ""
}
return string(b)
}

测试:

import (
"fmt"
"testing"
)

type Person struct {
Name string `json:"name"`
Age  int    `json:"age"`
}

func TestSlice_All(t *testing.T) {

people := []Person{
{"张三", 45},
{"李四", 2},
{"王五", 25},
{"小明", 15},
{"小红", 2},
{"小蓝", 7},
{"小白", 5},
{"小花", 34},
}
fmt.Println("原始数据:", people)
//需求:根据年龄进行升序排序
p := NewSlice(people).Sort(func(s Slice[Person], i, j int) bool {
return s[i].Age < s[j].Age
})
fmt.Println("排序后:", p) //结果:[{李四 2} {小红 2} {小白 5} {小蓝 7} {小明 15} {王五 25} {小花 34} {张三 45}]

//需求:过滤掉小于18岁的信息
p = NewSlice(people).Filter(func(pe Person) bool {
return pe.Age > 18
})
fmt.Println("过滤18岁以后的:", p) //结果:[{张三 45} {王五 25} {小花 34}]

//需求:向切片最后一个追加一个元素
p = NewSlice(people).Append(Person{
Name: "李玲",
Age:  23,
})
fmt.Println("追加元素后:", p) //结果:[{张三 45} {李四 2} {王五 25} {小明 15} {小红 2} {小蓝 7} {小白 5} {小花 34} {李玲 23}]

//需求:获取切片第一个(这块目的是经过其他方法处理过后,直接获取第一个,比较简单直接)
one := NewSlice(people).OnePointerObj()
fmt.Println("第一个元素:", *one) //结果:{张三 45}

//来一个比较常用的链式需求,需求:新增一个元素,并输出大于18岁且按照年龄进行升序排序的列表,最后以json方式输出
jsonStr := NewSlice(people).Append(Person{"李华", 35}).Sort(func(s Slice[Person], i, j int) bool {
return s[i].Age < s[j].Age
}).Filter(func(pe Person) bool {
return pe.Age > 18
}).ToJsonStr()
fmt.Println("结果:", jsonStr) //结果:[{"name":"王五","age":25},{"name":"小花","age":34},{"name":"李华","age":35},{"name":"张三","age":45}]

//后期有其他需求可以继续添加,这样就比较简单了
}


原文地址:https://blog.csdn.net/u011410254/article/details/140398608

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!