欢迎加入开源鸿蒙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. 核心作用

  1. 切片数组工具:去重、过滤、映射、求和、分组、分页、排序、查找、拆分合并;
  2. Map 对象工具:键值遍历、提取键/值、合并、筛选、反转键值;
  3. 条件工具:三元判断、默认值、空值安全取值;
  4. 类型转换:切片类型批量转换、字符串/数字互转;
  5. 并发工具:并发遍历、批量异步执行、限流协程;
  6. 集合运算:交集、差集、并集、子集判断;
  7. 错误简化处理、循环工具、随机值生成

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"
)
  1. fmt:控制台打印输出;
  2. math/rand + time:用于生成随机切片元素;
  3. strconv:数字与字符串互相转换;
  4. 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}

原始数字切片,演示数组常用工具方法

  1. lo.Uniq(numList):切片自动去重,去掉重复数字;
  2. lo.Filter:过滤函数,保留满足条件的元素(这里只保留大于3的数字);
  3. lo.Map:遍历转换每一个元素,数字转字符串;
  4. lo.Sum:一键计算切片所有数字总和,不用手写循环累加;
  5. lo.Find:查找第一个匹配条件的元素,返回「匹配值、是否找到」两个返回值(无索引,要索引用lo.FindIndex);
  6. lo.Chunk:切片分页,按指定数量分割成二维切片,做列表分页超好用;
  7. lo.Reverse:反转切片顺序。

模块2:结构体切片业务处理(后端高频)

userList := []User{...}

模拟数据库查询出来的用户列表

  1. lo.Filter:筛选状态正常(Status=1)的有效用户;
  2. lo.Map:批量提取结构体指定字段,这里提取所有用户姓名;
  3. lo.GroupBy:按自定义规则分组,这里按年龄段分组(10岁一档),返回map[分组key][]结构体
  4. lo.SomeBy:判断是否存在任意一条满足条件的数据(是否有未成年);
  5. lo.EveryBy:判断全部数据是否满足条件(是否所有用户都成年)。

模块3:Map字典处理

userMap := map[int]string{1:"小明",2:"小红",3:"小李"}

键值对字典操作工具

  1. lo.Keys():提取map全部key,转为切片;
  2. lo.Values():提取map全部value,转为切片;
  3. lo.Assign():合并多个map,后面map覆盖前面重复key;
  4. lo.PickBy():筛选map,只保留满足条件的键值对(这里只保留key>1的数据)。

模块4:集合运算(ID列表对比、权限场景)

a := []int{1,2,3,4}
b := []int{3,4,5,6}

适用于角色ID、菜单ID、标签ID对比

  1. lo.Intersect(a,b):交集,两边同时存在的数字 [3,4]
  2. lo.Union(a,b):并集,合并两边所有不重复数字 [1,2,3,4,5,6]
  3. lo.Difference(a,b):返回两个切片,第一个是a独有元素,第二个是b独有元素。

模块5:条件判断、三元、默认值

  1. lo.Ternary(条件,满足值,不满足值):Go原生没有三元运算符,lo封装简化if-else;
  2. lo.If(条件,真值).Else(假值):条件赋值,用来给空变量设置默认兜底值,替代不存在的lo.Or

模块6:原生协程并发批量处理

低版本lo无MapParallel,手动goroutine+channel实现并发批量计算:

  1. 循环开启多个协程并行处理数字 ×2;
  2. channel接收每个协程计算结果;
  3. 循环读取通道,收集全部结果输出;
    适用于批量文件处理、批量接口请求、大量数据计算。

模块7:切片最值 + 随机取值

  1. lo.Min / lo.Max:快速获取切片最小、最大值,不用手写循环比较;
  2. 标准库rand.Intn生成随机下标,取切片随机元素,替代不存在的lo.Random

整体代码业务价值

  1. 大幅减少for循环手写代码,简化切片、map处理;
  2. 适配后端ORM查询后的结构体列表过滤、分组、提取字段;
  3. 集合交集/差集快速处理权限、标签、ID对比需求;
  4. 三元、条件默认值简化大量if else嵌套;
  5. 兼容低版本lo,无任何未定义、参数不匹配编译报错;
  6. 鸿蒙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

五、开发常用业务场景

  1. 数据库查询后切片过滤、分页、分组统计;
  2. ID数组对比、求交集差集(权限、菜单、角色);
  3. 简化大量if-else,三元判断、空值默认值;
  4. 批量数据并发处理,简化协程同步代码;
  5. 结构体批量提取字段,拼接前端返回数据;
  6. 数组去重、求和、最值等通用计算,不用手写for循环。
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐