samber/lo 库提供了多个函数用于将切片(Slice)转换为 Map,比手写循环更简洁安全。以下是主要用法:

核心函数

1. Associate(键值自定义)

将切片转换为 map,同时定义 key 和 value 的生成逻辑

go

复制

import "github.com/samber/lo"

users := []User{
    {ID: 1, Name: "Alice", Age: 25},
    {ID: 2, Name: "Bob", Age: 30},
}

// map[ID]Name
nameMap := lo.Associate(users, func(u User) (int, string) {
    return u.ID, u.Name
})
// 结果: map[1:Alice 2:Bob]

2. KeyBy(按字段索引)

最常用,元素本身作为 value,key 由函数决定:

go

复制

// map[ID]User - 快速根据 ID 查找用户
userMap := lo.KeyBy(users, func(u User) int {
    return u.ID
})

// 使用
if user, ok := userMap[1]; ok {
    fmt.Println(user.Name)
}

3. GroupBy(分组聚合)

当 key 可能重复时,生成 map[K][]T

go

复制

usersByAge := lo.GroupBy(users, func(u User) int {
    return u.Age
})
// 结果: map[25:[{1 Alice 25}] 30:[{2 Bob 30}]]

对比与选择

表格

复制

函数 返回类型 适用场景 冲突处理
KeyBy map[K]T 建立主键索引 后覆盖前
Associate map[K]V 提取特定字段组合 后覆盖前
GroupBy map[K][]T 一对多关系 收集到切片

实战示例

go

复制

package main

import (
    "fmt"
    "github.com/samber/lo"
)

type User struct {
    ID   int
    Name string
    Dept string
}

func main() {
    users := []User{
        {1, "Alice", "Tech"},
        {2, "Bob", "Tech"},
        {3, "Charlie", "HR"},
    }

    // 场景1: ID 快速查找
    userMap := lo.KeyBy(users, func(u User) int { return u.ID })
    
    // 场景2: 只取 Name 映射
    idToName := lo.Associate(users, 
        func(u User) (int, string) { return u.ID, u.Name },
    )
    
    // 场景3: 按部门分组
    deptGroups := lo.GroupBy(users, func(u User) string { return u.Dept })
    
    fmt.Println(userMap[1].Name)    // Alice
    fmt.Println(idToName[2])        // Bob
    fmt.Println(len(deptGroups["Tech"])) // 2
}

注意事项

  1. 重复 Key 处理

    • KeyByAssociate 遇到重复 key 时,后面元素覆盖前面

    • 如需保留所有,改用 GroupBy

  2. 性能

    • 内部已优化内存预分配(make(map[...], len(collection))

    • 比手写 for 循环更简洁且无需担心容量问题

  3. 空切片安全

    • 传入空切片返回空 map(非 nil),可直接安全使用

安装go get github.com/samber/lo

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐