ZetCode

Golang slices.Collect

最后修改于 2025 年 4 月 20 日

本教程解释了如何在 Go 中使用 slices.Collect 函数。我们将通过实际的元素转换示例来介绍切片转换。

slices.Collect 函数通过对每个元素应用映射函数来转换切片的元素。它返回一个包含转换后值的新切片。

此函数对于转换数据类型或提取特定字段很有用。它遵循一种函数式编程模式,类似于其他语言中的 map。

基本 slices.Collect 示例

slices.Collect 最简单的用法是将数字转换为字符串。我们定义一个转换函数并将其应用于每个元素。

basic_collect.go
package main

import (
    "fmt"
    "slices"
    "strconv"
)

func main() {
    numbers := []int{1, 2, 3, 4, 5}
    
    strings := slices.Collect(numbers, func(n int) string {
        return strconv.Itoa(n)
    })
    
    fmt.Println("Converted strings:", strings)
}

我们创建一个整数切片,并将每个整数转换为字符串表示形式。匿名函数定义了我们对每个元素的转换逻辑。

提取结构体字段

slices.Collect 可以从结构体元素中提取特定字段。此示例从 Person 结构体切片中收集姓名。

extract_fields.go
package main

import (
    "fmt"
    "slices"
)

type Person struct {
    Name string
    Age  int
}

func main() {
    people := []Person{
        {"Alice", 25},
        {"Bob", 30},
        {"Charlie", 17},
    }
    
    names := slices.Collect(people, func(p Person) string {
        return p.Name
    })
    
    fmt.Println("Names:", names)
}

转换函数访问每个人的 Name 字段。结果是一个只包含原始结构体姓名的切片。

类型转换

我们可以使用 slices.Collect 在数值类型之间进行类型转换。此示例将 int32 值转换为 float64。

type_conversion.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    ints := []int32{10, 20, 30, 40, 50}
    
    floats := slices.Collect(ints, func(n int32) float64 {
        return float64(n)
    })
    
    fmt.Printf("Converted floats: %v (type: %T)\n", floats, floats)
}

每个 int32 值都被转换为 float64。类型转换在更改底层表示的同时保留了数值。

计算派生值

可以在转换函数中执行复杂的计算。此示例计算数字的平方。

derived_values.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    numbers := []int{1, 2, 3, 4, 5}
    
    squares := slices.Collect(numbers, func(n int) int {
        return n * n
    })
    
    fmt.Println("Squares:", squares)
}

转换函数对每个输入数字进行平方。结果包含计算后的值,而原始切片保持不变。

空切片行为

slices.Collect 可以优雅地处理空切片。此示例演示了其对空输入的行为。

empty_slice.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    var empty []int
    
    result := slices.Collect(empty, func(n int) string {
        return "unused" // Never called
    })
    
    fmt.Println("Result for empty slice:", result)
    fmt.Println("Length:", len(result))
}

当没有要处理的元素时,该函数将返回目标类型的空切片。在这种情况下,转换函数永远不会被调用。

性能注意事项

对于大型切片,转换函数的性能很重要。此示例对不同的方法进行了基准测试。

performance.go
package main

import (
    "fmt"
    "slices"
    "time"
)

func main() {
    largeSlice := make([]int, 1_000_000)
    for i := range largeSlice {
        largeSlice[i] = i
    }
    
    // Simple transformation
    start := time.Now()
    _ = slices.Collect(largeSlice, func(n int) int {
        return n * 2
    })
    fmt.Println("Simple transformation:", time.Since(start))
    
    // Complex transformation
    start = time.Now()
    _ = slices.Collect(largeSlice, func(n int) float64 {
        return float64(n) * 1.5 / 3.14159
    })
    fmt.Println("Complex transformation:", time.Since(start))
}

执行时间取决于转换的复杂性。新切片的内存分配也会影响整体性能。

实际示例:API 响应处理

这个实际示例使用 slices.Collect 处理 API 响应。我们从 JSON 响应中提取特定字段。

api_processing.go
package main

import (
    "encoding/json"
    "fmt"
    "slices"
)

type User struct {
    ID       int    `json:"id"`
    Username string `json:"username"`
    Email    string `json:"email"`
    Active   bool   `json:"active"`
}

func main() {
    responses := []string{
        `{"id":1,"username":"alice","email":"alice@example.com","active":true}`,
        `{"id":2,"username":"bob","email":"bob@example.com","active":false}`,
        `{"id":3,"username":"charlie","email":"charlie@example.com","active":true}`,
    }
    
    users := slices.Collect(responses, func(s string) User {
        var u User
        json.Unmarshal([]byte(s), &u)
        return u
    })
    
    usernames := slices.Collect(users, func(u User) string {
        return u.Username
    })
    
    fmt.Println("Active users:", usernames)
}

我们首先将 JSON 字符串转换为 User 结构体,然后提取用户名。这展示了为数据处理链接多个转换。

来源

Go 实验性切片包文档

本教程通过在各种场景下转换切片元素的实际示例,涵盖了 Go 中的 slices.Collect 函数。

作者

我叫 Jan Bodnar,是一名热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直在撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出所有 Go 教程