1. 介绍
Go-funk
是基于反射(reflect
)实现的一个现代Go
工具库,封装了对slice/map/struct/string
等的操作。
2. 下载
go get github.com/thoas/go-funk
import github.com/thoas/go-funk
|
3. 切片(slice
)操作
3.1 判断元素是否存在
funk.Contains
: 接收任意类型。
funk.ContainsX
: X
代表具体类型,如:ContainsInt、ContainsString...
func TestExist(t *testing.T) { fmt.Println("str->", funk.Contains([]string{"a", "b"}, "a")) fmt.Println("int->", funk.ContainsInt([]int{1, 2}, 1)) }
|
3.2 查找元素第一次出现位置
funk.IndexOf
: 接收任意类型,不存在则返回-1
。
funk.IndexOfX
: X
代表具体类型,不存在则返回-1
。
func TestIndexOf(t *testing.T) { strArr := []string{"go", "java", "c", "java"} fmt.Println("c: ", funk.IndexOfString(strArr, "c")) fmt.Println("java: ", funk.IndexOfString(strArr, "java")) fmt.Println("go: ", funk.IndexOf(strArr, "go")) fmt.Println("php: ", funk.IndexOfString(strArr, "php")) }
|
3.3 查找元素最后一次出现位置
funk.LastIndexOf
: 接收任意类型,不存在则返回-1
。
funk.LastIndexOfX
: X
代表具体类型,不存在则返回-1
。
func TestLastOf(t *testing.T) { strArr := []string{"go", "java", "c", "java"} fmt.Println("c: ", funk.LastIndexOfString(strArr, "c")) fmt.Println("java: ", funk.LastIndexOfString(strArr, "java")) fmt.Println("go: ", funk.LastIndexOf(strArr, "go")) fmt.Println("php: ", funk.LastIndexOf(strArr, "php")) }
|
3.4 批量查找(都有则True)
func Every(in interface{}, elements ...interface{}) bool
- 当
elements
都在in
中时,则返回true
; 否则为false
;
func TestEvery(t *testing.T) { strArr := []string{"go", "java", "c", "python"} fmt.Println("都存在:", funk.Every(strArr, "go", "c")) fmt.Println("有一个不存在:", funk.Every(strArr, "php", "go")) fmt.Println("都不存在:", funk.Every(strArr, "php", "c++")) }
|
3.5 批量查找(有一则True)
func Some(in interface{}, elements ...interface{}) bool
- 当
elements
至少有一个在in
中时,则返回true
; 否则为false
;
func TestSome(t *testing.T) { strArr := []string{"go", "java", "c", "python"} fmt.Println("都存在:", funk.Some(strArr, "go", "c")) fmt.Println("至少一个存在:", funk.Some(strArr, "php", "go")) fmt.Println("都不存在:", funk.Some(strArr, "php", "c++")) }
|
3.6 获取最后或第一个元素
func TestLastOrFirst(t *testing.T) { number := []int{10, 30, 12, 23} fmt.Println("Head: ", funk.Head(number)) fmt.Println("Last: ", funk.Last(number)) }
|
3.7 用元素填充切片
func Fill(in interface{}, fillValue interface{}) (interface{}, error)
func TestFill(t *testing.T) { var data = make([]int, 3) fill, _ := funk.Fill(data, 100) fmt.Printf("fill: %v \n", fill) input := []int{1, 2, 3} result, _ := funk.Fill(input, 2) fmt.Printf("result: %v \n", result) var structData = make([]Student, 2) stuInfo, _ := funk.Fill(structData, Student{Name: "张三", Age: 18}) fmt.Printf("stuInfo: %v \n", stuInfo) }
|
3.8 取两个切片共同元素结果集
Join(larr, rarr interface{}, fnc JoinFnc)
: 当fnc=funk.InnerJoin
,代表合并两个任意类型切片。
JoinXXX(larr, rarr interface{}, fnc JoinFnc)
: 指定类型合并,推荐使用。
type cus struct { Name string Age int Home string } func TestJoin(t *testing.T) { a := []int64{1, 3, 5, 7} b := []int64{3, 7} join := funk.Join(a, b, funk.InnerJoin) fmt.Println("join = ", join) joinInt64 := funk.JoinInt64(a, b, funk.InnerJoinInt64) fmt.Println("joinInt64 = ", joinInt64) sliceA := []cus{ {"张三", 20, "北京"}, {"李四", 22, "南京"}, } sliceB := []cus{ {"张三", 20, "北京"}, {"李四", 22, "上海"}, } res := funk.Join(sliceA, sliceB, funk.InnerJoin) fmt.Println("自定义结构体: ", res) }
|
3.9 获取去掉两切片共同元素结果集
同样使用Join
和JoinXXX
方法,而fnc
设置成funk.OuterJoin
func TestDiffSlice(t *testing.T) { a := []int64{1, 3, 5, 7} b := []int64{3, 7, 10} join := funk.Join(a, b, funk.OuterJoin) fmt.Println("OuterJoin = ", join) joinInt64 := funk.JoinInt64(a, b, funk.OuterJoinInt64) fmt.Println("joinInt64 = ", joinInt64) sliceA := []cus{ {"张三", 20, "北京"}, {"李四", 22, "南京"}, } sliceB := []cus{ {"张三", 20, "北京"}, {"李四", 22, "上海"}, } res := funk.Join(sliceA, sliceB, funk.OuterJoin) fmt.Println("自定义结构体: ", res) }
|
3.10 求只存在某切片的元素(除去共同元素)
func TestLeftAndRightJoin(t *testing.T) { a := []int64{10, 20, 30} b := []int64{30, 40} leftJoin := funk.Join(a, b, funk.LeftJoin) fmt.Println("只在a切片的元素: ", leftJoin) rightJoin := funk.Join(a, b, funk.RightJoin) fmt.Println("只在b切片的元素: ", rightJoin) }
|
3.11 分别去掉两个切片共同元素(两结果集)
func TestDifferent(t *testing.T) { one := []interface{}{1, "go", 3.2, []int8{10}} two := []interface{}{2, "go", 3.2, []int{20}} oneRes, twoRes := funk.Difference(one, two) fmt.Println("oneRes: ", oneRes) fmt.Println("twoRes: ", twoRes)
str1 := []string{"go", "php", "java"} str2 := []string{"c", "python", "java"} res, res1 := funk.DifferenceString(str1, str2) fmt.Println("res: ", res) fmt.Println("res1: ", res1) }
|
3.12 遍历切片
ForEach
: 从左边遍历切片。
ForEachRight
: 从右边遍历切片。
func TestForeachSlice(t *testing.T) { var leftRes []int funk.ForEach([]int{1, 2, 3, 4}, func(x int) { leftRes = append(leftRes, x*2) }) fmt.Println("ForEach:", leftRes) var rightRes []int funk.ForEachRight([]int{1, 2, 3, 4}, func(x int) { rightRes = append(rightRes, x*2) }) fmt.Println("ForEachRight:", rightRes) }
|
3.13 删除首或尾
func TestDelLastOrFirst(t *testing.T) { a := []int{1, 2, 3, 4, 5, 6, 7} fmt.Println(funk.Tail(a)) fmt.Println(funk.Initial(a)) }
|
3.14 判断A切片是否属于B切片子集
Subset(x interface{}, y interface{}) bool
: 判断x
是否属于y
的切片。
func TestSubset(t *testing.T) { fmt.Println("是否属于子集:", funk.Subset([]int{1}, []int{1, 2})) subStu1 := []Student{{Name: "张三", Age: 18}} subStu2 := []Student{{Name: "张三", Age: 22}} allStu := []Student{ {Name: "张三", Age: 18}, {Name: "李四", Age: 22}, } fmt.Println("subStu1: ", funk.Subset(subStu1, allStu)) fmt.Println("subStu2: ", funk.Subset(subStu2, allStu)) fmt.Println("判断空集:", funk.Subset([]int{}, []int{1, 2})) }
|
3.15 分组
Chunk(arr interface{}, size int) interface{}
: 把arr
按照每组size个
进行分组
func TestChunk(t *testing.T) { a := []int{1, 2, 3, 4, 5, 6, 7} fmt.Println(funk.Chunk(a, 2)) stuList := []Student{ {Name: "张三", Age: 18}, {Name: "小明", Age: 20}, {Name: "李四", Age: 22}, {Name: "赵武", Age: 32}, {Name: "小英", Age: 19}, } fmt.Println(funk.Chunk(stuList, 2)) }
|
3.16 把结构体切片转成map
ToMap(in interface{}, pivot string) interface{}
: 把切片in
,转成以pivot
为key
的map
。
func TestToMap(t *testing.T) { bookList := []Book{ {Id: 1, Name: "西游记"}, {Id: 2, Name: "水浒传"}, {Id: 3, Name: "三国演义"}, } fmt.Println("结果:", funk.ToMap(bookList, "Id")) }
|
3.17 把切片值转成Map
中的Key
func TestMap(t *testing.T) { r := funk.Map([]int{1, 2, 3, 4}, func(x int) (int, string) { return x, "go" }) fmt.Println("r=", r) }
|
3.18 把二维切片转成一维切片
func TestFlatMap(t *testing.T) { r := funk.FlatMap([][]int{{1}, {2}, {3}, {4}}, func(x []int) []int { return x }) fmt.Printf("%#v\n", r) }
|
3.19 打乱切片
func TestShuffle(t *testing.T) { a := []int{0, 1, 2, 3, 4, 5, 6, 7} for i := 1; i <= 3; i++ { fmt.Println(fmt.Sprintf("第%v次打乱a", i), funk.Shuffle(a)) } }
|
3.20 反转切片
func TestReverse(t *testing.T) { fmt.Println("ReverseInt:", funk.ReverseInt([]int{1, 2, 3, 4, 5, 6})) fmt.Println("Reverse,任意类型:", funk.Reverse([]interface{}{1, "2", 3.02, 4, "5", 6})) fmt.Println("Reverse,Str:", funk.ReverseStrings([]string{"a", "b", "c", "d"})) }
|
3.21 元素去重
func TestUniq(t *testing.T) { a := []int64{1, 2, 3, 4, 3, 2, 1} fmt.Println("Uniq:", funk.Uniq(a)) fmt.Println("UniqInt64:", funk.UniqInt64(a)) b := []string{"php", "go", "c", "go"} fmt.Println("UniqString:", funk.UniqString(b)) }
|
3.22 删除制定元素
func TestWithOut(t *testing.T) { b := []int{10, 20, 30, 40} without := funk.Without(b, 30) fmt.Println("删除30:", without) stuList := []Student{ {Name: "张三", Age: 18}, {Name: "李四", Age: 22}, {Name: "范五", Age: 24}, } res := funk.Without(stuList, Student{Name: "李四", Age: 22}) fmt.Println("删除李四:", res) }
|
4. 映射(map
)操作
4.1 获取所有的Key
func TestMapKeys(t *testing.T) { res := map[string]int{ "张三": 18, "李四": 20, "赵武": 25, } keys := funk.Keys(res) fmt.Printf("keys: %#v %T \n", keys, keys) }
|
4.2 获取所有的Value
func TestMapValues(t *testing.T) { res := map[string]int{ "张三": 18, "李四": 20, "赵武": 25, } values := funk.Values(res) fmt.Printf("values: %#v %T \n", values, values) }
|
5. 结构体(struct
)切片操作
5.1 取结构体某元素为切片
func TestGetToSlice(t *testing.T) { userList := []User{ { Name: "张三", Home: struct { City string }{"北京"}, }, { Name: "小明", Home: struct { City string }{"南京"}, }, } names := funk.Get(userList, "Name") fmt.Println("names:", names) homes := funk.Get(userList, "Home.City") fmt.Println("homes:", homes) }
|
6. 判断操作
6.1 判断相等
type Student struct { Name string Age int }
func TestIsEqual(t *testing.T) { fmt.Println("对比字符串:", funk.IsEqual("a", "a")) fmt.Println("对比int:", funk.IsEqual(1, 1)) fmt.Println("对比float64:", funk.IsEqual(float64(1), float64(1))) stu1 := Student{Name: "张三", Age: 18} stu2 := Student{Name: "张三", Age: 18} fmt.Println("对比结构体:", funk.IsEqual(stu1, stu2)) }
|
6.2 判断类型一致
func TestIsType(t *testing.T) { var a, b int8 = 1, 2 fmt.Println("A: ", funk.IsType(a, b)) c := 3 d := "3" fmt.Println("B:", funk.IsType(c, d)) }
|
6.3 判断array|slice
func TestCollect(t *testing.T) { a := []int{1, 2, 3} b := "str" c := []Student{ {Name: "张三", Age: 18}, {Name: "李四", Age: 18}, } d := [2]string{"c", "go"} fmt.Println("a:", funk.IsCollection(a)) fmt.Println("b:", funk.IsCollection(b)) fmt.Println("c:", funk.IsCollection(c)) fmt.Println("d:", funk.IsCollection(d)) }
|
6.4 判断空
funk.IsEmpty(obj interface{})
: 判断为空。
funk.NotEmpty(obj interface{})
: 判断不为空。
func TestIsEmpty(t *testing.T) { fmt.Println("空结构体", funk.IsEmpty([]int{})) fmt.Println("空字符串:", funk.IsEmpty("")) fmt.Println("0:", funk.IsEmpty(0)) fmt.Println("'0':", funk.IsEmpty("0")) fmt.Println("nil:", funk.IsEmpty(nil)) }
|
7. 类型转换
7.1 任意数字转float64
func ToFloat64(x interface{}) (float64, bool)
- 将任何数字类型,转成
float64
类型,**@注:只能是数字类型: uint8、uint16、uint32、uint64、int、int8、int16、int32、int64、float32、float64**
func TestToFloat64(t *testing.T) { d1, _ := funk.ToFloat64(10) fmt.Printf("d1 = %v %T \n", d1, d1) d2, err := funk.ToFloat64("10") fmt.Printf("d2 = %v %v \n", d2, err) }
|
7.2 将X
转成[]X
func TestSliceOf(t *testing.T) { a := []int{10, 20, 30} fmt.Printf("%v %T \n", funk.SliceOf(a), funk.SliceOf(a)) fmt.Printf("%v %T \n", funk.SliceOf("go"), funk.SliceOf("go")) }
|
8.字符串操作
8.1 根据字符串生成切片
func Shard(str string, width int, depth int, restOnly bool) []string
width
: 代表根据几个字节生成一个元素。
depth
: 将字符串前x
个元素转成切片。
restOnly
: 当为false
时,最后一个元素为原字符串,当为true
时,最后一个元素为原字符串剩余元素
func TestShard(t *testing.T) { tokey := "Hello,Word" shard := funk.Shard(tokey, 1, 5, false) shard1 := funk.Shard(tokey, 1, 5, true) fmt.Println("shard: ", shard) fmt.Println("shard1: ", shard1) shard2 := funk.Shard(tokey, 2, 5, false) shard22 := funk.Shard(tokey, 2, 5, true) fmt.Println("shard2: ", shard2) fmt.Println("shard22: ", shard22) }
|
9.数字计算
9.1 最大值(Max
)
func TestMax(t *testing.T) { fmt.Println("MaxInt:", funk.MaxInt([]int{30, 10, 8, 11})) fmt.Println("MaxFloat64:", funk.MaxFloat64([]float64{10.2, 11.0, 8.03})) fmt.Println("MaxString:", funk.MaxString([]string{"a", "d", "c", "b"})) }
|
9.2 最小值(Min
)
func TestMin(t *testing.T) { fmt.Println("MinInt:", funk.MinInt([]int{30, 10, 8, 11})) fmt.Println("MinFloat64:", funk.MinFloat64([]float64{10.2, 11.0, 8.03})) fmt.Println("MinString:", funk.MinString([]string{"a", "d", "c", "b"})) }
|
9.3 求和(Sum
)
func TestSum(t *testing.T) { a := []int{5, 10, 15, 20} fmt.Println("int sum:", funk.Sum(a)) b := []float64{5.11, 2.23, 3.31, 0.32} fmt.Println("float64 sum:", funk.Sum(b)) }
|
9.4 求乘积(Product
)
func TestProduct(t *testing.T) { a := []int{2, 3, 4, 5} fmt.Println("int Product:", funk.Product(a)) b := []float64{1.1, 1.2, 1.3, 1.4} fmt.Println("float64 Product:", funk.Product(b)) }
|
10. 其他操作
10.1 生成随机数
func TestRandom(t *testing.T) { for i := 1; i <= 3; i++ { fmt.Println(funk.RandomInt(1, 100)) } }
|
10.2 生成随机字符串
func TestRandomString(t *testing.T) { for i := 1; i <= 3; i++ { fmt.Println("从默认字符串生成:", funk.RandomString(i)) fmt.Println("从指定字符串生成:", funk.RandomString(i, []rune{'您', '好', '北', '京'})) } }
|
10.3 三元运算
func TestShortIf(t *testing.T) { fmt.Println("10 > 5 :", funk.ShortIf(10 > 5, 10, 5)) fmt.Println("10.0 == 10 : ", funk.ShortIf(10.0 == 10, "yes", "no")) fmt.Println("'a' == 'b' : ", funk.ShortIf('a' == 'b', "equal chars", "unequal chars")) }
|