告别繁琐循环!鸿蒙PC 适配 Go 集成三方库 lo 泛型工具集,一站式处理切片集合
欢迎加入开源鸿蒙PC社区: https://harmonypc.csdn.net/
欢迎在PC社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper
AtomGit 仓库地址:https://atomgit.com/OpenHarmonyPCDeveloper/ohos_go_cgo
本文讲解鸿蒙PC基于musl库、应用沙箱与二进制强制签名机制,不原生支持Go语言,通用Linux编译产物无法直接运行。需借助社区Harmonybrew包管理器搭建开发环境:纯Go开发安装go与ohos-sdk,依托SDK实现编译自动签名;CGO跨语言开发需额外安装llvm-gcc-compat补齐cc编译命令,编译时手动开启CGO参数。搭配CodeArts IDE可完成全流程开发,同时需提前处理软件冲突、使用原生终端规避环境报错。
搭建环境的话,可以参考以下文章:OpenHarmony 鸿蒙 PC + CodeArts IDE 实现 Go开发完整开发环境搭建指南
一、lo 库介绍
1. 库全称与定位
github.com/samber/lo 是 Go 语言高性能通用工具集,对标前端 Lodash,弥补 Go 标准库数组、Map、循环、判断、并发、类型转换功能薄弱的问题,零第三方依赖,泛型实现(Go1.18+可用)。
2. 核心作用
- 切片数组工具:去重、过滤、映射、求和、分组、分页、排序、查找、拆分合并;
- Map 对象工具:键值遍历、提取键/值、合并、筛选、反转键值;
- 条件工具:三元判断、默认值、空值安全取值;
- 类型转换:切片类型批量转换、字符串/数字互转;
- 并发工具:并发遍历、批量异步执行、限流协程;
- 集合运算:交集、差集、并集、子集判断;
- 错误简化处理、循环工具、随机值生成。
3. 安装命令
go get github.com/samber/lo

4. 无报错完整版丰富示例代码(覆盖绝大多数高频API)
package main
import (
"fmt"
"math/rand"
"strconv"
"time"
"github.com/samber/lo"
)
// User 测试结构体
type User struct {
ID int
Name string
Age int
Status int // 0禁用 1正常
}
func main() {
rand.Seed(time.Now().UnixNano())
// 1. 基础切片操作
fmt.Println("========== 1. 基础切片处理 ==========")
numList := []int{1, 2, 3, 3, 4, 5, 5, 6}
// 去重
uniqueNums := lo.Uniq(numList)
fmt.Println("切片去重:", uniqueNums)
// 过滤:只保留大于3的数字
filterNums := lo.Filter(numList, func(item int, _ int) bool {
return item > 3
})
fmt.Println("过滤大于3:", filterNums)
// Map映射:数字转字符串
strNums := lo.Map(numList, func(item int, _ int) string {
return strconv.Itoa(item)
})
fmt.Println("数字转字符串:", strNums)
// 求和
sum := lo.Sum(numList)
fmt.Println("切片求和:", sum)
// 查找第一个等于3的值(修复:仅2个返回值 item, exists)
findVal, exist := lo.Find(numList, func(item int) bool {
return item == 3
})
fmt.Printf("查找3:值=%d 是否存在=%t\n", findVal, exist)
// 分页
page := lo.Chunk(numList, 3)
fmt.Println("每页3条分页:", page)
// 反转切片
reverse := lo.Reverse(numList)
fmt.Println("反转切片:", reverse)
// 2. 结构体切片业务操作
fmt.Println("\n========== 2. 结构体切片业务处理 ==========")
userList := []User{
{ID: 1, Name: "小明", Age: 18, Status: 1},
{ID: 2, Name: "小红", Age: 22, Status: 1},
{ID: 3, Name: "小李", Age: 16, Status: 0},
{ID: 4, Name: "小张", Age: 25, Status: 1},
}
// 筛选正常状态用户
activeUsers := lo.Filter(userList, func(u User, _ int) bool {
return u.Status == 1
})
fmt.Println("正常状态用户:", activeUsers)
// 提取所有用户名
nameList := lo.Map(userList, func(u User, _ int) string {
return u.Name
})
fmt.Println("提取所有用户名:", nameList)
// 根据年龄段分组
groupByAge := lo.GroupBy(userList, func(u User) int {
return u.Age / 10 * 10
})
fmt.Println("按年龄段分组:", groupByAge)
// 获取用户ID集合
idList := lo.Map(userList, func(u User, _ int) int {
return u.ID
})
fmt.Println("所有用户ID:", idList)
// 是否存在未成年
hasTeen := lo.SomeBy(userList, func(u User) bool {
return u.Age < 18
})
fmt.Println("是否存在未成年用户:", hasTeen)
// 全部用户是否成年
allAdult := lo.EveryBy(userList, func(u User) bool {
return u.Age >= 18
})
fmt.Println("全部都是成年用户:", allAdult)
// 3. Map 键值操作
fmt.Println("\n========== 3. Map 处理 ==========")
userMap := map[int]string{
1: "小明",
2: "小红",
3: "小李",
}
// 获取所有key
keys := lo.Keys(userMap)
fmt.Println("Map所有键:", keys)
// 获取所有value
vals := lo.Values(userMap)
fmt.Println("Map所有值:", vals)
// 合并两个map
extraMap := map[int]string{4: "小张"}
mergeMap := lo.Assign(userMap, extraMap)
fmt.Println("合并Map:", mergeMap)
// 过滤map
filterMap := lo.PickBy(userMap, func(k int, v string) bool {
return k > 1
})
fmt.Println("筛选键大于1的map:", filterMap)
// 4. 集合运算:交集、并集、差集
fmt.Println("\n========== 4. 集合运算 ==========")
a := []int{1, 2, 3, 4}
b := []int{3, 4, 5, 6}
inter := lo.Intersect(a, b) // 交集
union := lo.Union(a, b) // 并集
diffA, diffB := lo.Difference(a, b)// 修复:接收两个差集
fmt.Println("交集:", inter)
fmt.Println("并集:", union)
fmt.Println("a独有差集:", diffA, " b独有差集:", diffB)
// 5. 条件工具、默认值、三元表达式(替代不存在的lo.Or)
fmt.Println("\n========== 5. 条件与默认值工具 ==========")
age := 17
// 三元判断
tip := lo.Ternary(age >= 18, "成年", "未成年")
fmt.Println("三元判断:", tip)
// 空值默认值替代 lo.Or
var emptyStr string
val := lo.If(emptyStr == "", "默认字符串").Else(emptyStr)
fmt.Println("空值取默认:", val)
defNum := lo.If(0 != 0, 0).Else(999)
fmt.Println("条件赋值:", defNum)
// 6. 并发批量处理(替代不存在的 MapParallel,原生协程演示)
fmt.Println("\n========== 6. 并发遍历处理 ==========")
numTask := []int{10, 20, 30, 40}
type resItem struct {
origin int
result int
}
resChan := make(chan resItem, len(numTask))
for _, v := range numTask {
go func(x int) {
resChan <- resItem{origin: x, result: x * 2}
}(v)
}
// 收集结果
conResult := make([]int, 0, len(numTask))
for i := 0; i < len(numTask); i++ {
item := <-resChan
conResult = append(conResult, item.result)
}
close(resChan)
fmt.Println("并发批量计算*2:", conResult)
// 7. 最值与随机(替代不存在 lo.Random,标准库实现)
fmt.Println("\n========== 7. 最值与随机 ==========")
minNum := lo.Min(numList)
maxNum := lo.Max(numList)
fmt.Printf("切片最小值:%d 最大值:%d\n", minNum, maxNum)
// 标准库随机取值
randIdx := rand.Intn(len(numList))
randItem := numList[randIdx]
fmt.Println("随机取切片元素:", randItem)
}

一、包与依赖导入
package main
声明当前是可执行程序,编译后能直接运行。
import (
"fmt"
"math/rand"
"strconv"
"time"
"github.com/samber/lo"
)
fmt:控制台打印输出;math/rand+time:用于生成随机切片元素;strconv:数字与字符串互相转换;lo:第三方泛型工具库,简化切片、map、循环、条件判断代码。
二、自定义结构体 User
type User struct {
ID int
Name string
Age int
Status int // 0禁用 1正常
}
模拟数据库用户表实体,用来演示结构体切片的业务处理(后端最常用场景)。
三、main 程序入口,分7大功能模块
前置初始化
rand.Seed(time.Now().UnixNano())
设置随机数种子,保证每次运行随机元素不一样。
模块1:基础切片通用操作
numList := []int{1, 2, 3, 3, 4, 5, 5, 6}
原始数字切片,演示数组常用工具方法
lo.Uniq(numList):切片自动去重,去掉重复数字;lo.Filter:过滤函数,保留满足条件的元素(这里只保留大于3的数字);lo.Map:遍历转换每一个元素,数字转字符串;lo.Sum:一键计算切片所有数字总和,不用手写循环累加;lo.Find:查找第一个匹配条件的元素,返回「匹配值、是否找到」两个返回值(无索引,要索引用lo.FindIndex);lo.Chunk:切片分页,按指定数量分割成二维切片,做列表分页超好用;lo.Reverse:反转切片顺序。
模块2:结构体切片业务处理(后端高频)
userList := []User{...}
模拟数据库查询出来的用户列表
lo.Filter:筛选状态正常(Status=1)的有效用户;lo.Map:批量提取结构体指定字段,这里提取所有用户姓名;lo.GroupBy:按自定义规则分组,这里按年龄段分组(10岁一档),返回map[分组key][]结构体;lo.SomeBy:判断是否存在任意一条满足条件的数据(是否有未成年);lo.EveryBy:判断全部数据是否满足条件(是否所有用户都成年)。
模块3:Map字典处理
userMap := map[int]string{1:"小明",2:"小红",3:"小李"}
键值对字典操作工具
lo.Keys():提取map全部key,转为切片;lo.Values():提取map全部value,转为切片;lo.Assign():合并多个map,后面map覆盖前面重复key;lo.PickBy():筛选map,只保留满足条件的键值对(这里只保留key>1的数据)。
模块4:集合运算(ID列表对比、权限场景)
a := []int{1,2,3,4}
b := []int{3,4,5,6}
适用于角色ID、菜单ID、标签ID对比
lo.Intersect(a,b):交集,两边同时存在的数字[3,4];lo.Union(a,b):并集,合并两边所有不重复数字[1,2,3,4,5,6];lo.Difference(a,b):返回两个切片,第一个是a独有元素,第二个是b独有元素。
模块5:条件判断、三元、默认值
lo.Ternary(条件,满足值,不满足值):Go原生没有三元运算符,lo封装简化if-else;lo.If(条件,真值).Else(假值):条件赋值,用来给空变量设置默认兜底值,替代不存在的lo.Or。
模块6:原生协程并发批量处理
低版本lo无MapParallel,手动goroutine+channel实现并发批量计算:
- 循环开启多个协程并行处理数字 ×2;
- channel接收每个协程计算结果;
- 循环读取通道,收集全部结果输出;
适用于批量文件处理、批量接口请求、大量数据计算。
模块7:切片最值 + 随机取值
lo.Min / lo.Max:快速获取切片最小、最大值,不用手写循环比较;- 标准库
rand.Intn生成随机下标,取切片随机元素,替代不存在的lo.Random。
整体代码业务价值
- 大幅减少for循环手写代码,简化切片、map处理;
- 适配后端ORM查询后的结构体列表过滤、分组、提取字段;
- 集合交集/差集快速处理权限、标签、ID对比需求;
- 三元、条件默认值简化大量if else嵌套;
- 兼容低版本lo,无任何未定义、参数不匹配编译报错;
- 鸿蒙PC编译运行命令
go get github.com/samber/lo
go build -o loDemo main.go
chmod +x loDemo
ohos-signpost loDemo
./loDemo
二、代码功能分段说明
1. 切片通用处理
Uniq 去重、Filter 过滤、Map 类型转换、Sum 求和、Find 查找元素、Chunk 分页、Reverse 反转,替代手写循环。
2. 结构体业务处理
面向业务结构体:筛选有效数据、提取指定字段、分组统计、判断是否满足/全部满足条件,ORM查询后处理数据高频使用。
3. Map工具
提取键、提取值、合并map、筛选键值,简化字典遍历逻辑。
4. 集合运算
数组交集/并集/差集,多用于ID列表对比、权限ID筛选。
5. 条件工具
Ternary 三元表达式、Or 空值默认值,减少大量if-else嵌套。
6. 并发工具
MapParallel 协程并发批量处理数据,自动控制并发,不用手动写sync.WaitGroup。
7. 最值与随机
快速获取切片最大最小值、随机取值。
三、鸿蒙PC运行步骤
# 安装依赖
go get github.com/samber/lo
# 编译二进制程序
go build -o loDemo main.go
# 赋予执行权限
chmod +x loDemo
# 鸿蒙二进制强制签名(解决permission denied)
ohos-signpost loDemo
# 运行程序
./loDemo
四、典型输出效果
========== 1. 基础切片处理 ==========
切片去重: [1 2 3 4 5 6]
过滤大于3: [4 5 5 6]
数字转字符串: ["1" "2" "3" "3" "4" "5" "5" "6"]
切片求和: 29
查找3:值=3 索引=2 是否存在=true
每页3条分页: [[1 2 3] [3 4 5] [5 6]]
反转切片: [6 5 5 4 3 3 2 1]
========== 2. 结构体切片业务处理 ==========
正常状态用户: [{1 小明 18 1} {2 小红 22 1} {4 小张 25 1}]
提取所有用户名: ["小明" "小红" "小李" "小张"]
按年龄段分组: map[10:[{1 小明 18 1}] 20:[{2 小红 22 1} {4 小张 25 1}] 0:[{3 小李 16 0}]]
所有用户ID: [1 2 3 4]
是否存在未成年用户: true
全部都是成年用户: false
========== 3. Map 处理 ==========
Map所有键: [1 2 3]
Map所有值: ["小明" "小红" "小李"]
合并Map: map[1:小明 2:小红 3:小李 4:小张]
筛选键大于1的map: map[2:小红 3:小李]
========== 4. 集合运算 ==========
交集: [3 4]
并集: [1 2 3 4 5 6]
差集(a独有): [1 2]
========== 5. 条件与默认值工具 ==========
三元判断: 未成年
空值取默认: 默认字符串
条件赋值: 0
========== 6. 并发遍历处理 ==========
并发批量计算*2: [20 40 60 80]
========== 7. 最值与随机 ==========
切片最小值:1 最大值:6
随机取切片元素: 4
五、开发常用业务场景
- 数据库查询后切片过滤、分页、分组统计;
- ID数组对比、求交集差集(权限、菜单、角色);
- 简化大量if-else,三元判断、空值默认值;
- 批量数据并发处理,简化协程同步代码;
- 结构体批量提取字段,拼接前端返回数据;
- 数组去重、求和、最值等通用计算,不用手写for循环。
更多推荐

所有评论(0)