ZetCode

Golang slices.Values

最后修改于 2025 年 4 月 20 日

本教程将讲解如何在 Go 中使用 `slices.Values` 函数。我们将通过提取值的实际示例来介绍映射操作。

`slices.Values` 函数以切片的形式返回映射的值。它是 Go 1.21 中引入的 Go 实验性 slices 包的一部分。

当您需要独立于键来处理映射的值时,此函数非常有用。返回的切片顺序是随机的,与 Go 的映射迭代顺序一致。

基本 slices.Values 示例

`slices.Values` 最简单的用法是从字符串映射中提取值。我们将创建一个映射并获取其所有值作为切片。

basic_values.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    fruitMap := map[string]int{
        "apple":  5,
        "banana": 3,
        "cherry": 7,
    }
    
    values := slices.Values(fruitMap)
    fmt.Println("Fruit quantities:", values)
}

我们创建了一个从水果名称到数量的映射。`slices.Values` 返回一个包含所有值(5、3、7)的切片,顺序是随机的。

使用结构体值

`slices.Values` 可以处理包含结构体值的映射。此示例从按 ID 键控的映射中提取 Person 对象。

struct_values.go
package main

import (
    "fmt"
    "slices"
)

type Person struct {
    Name string
    Age  int
}

func main() {
    people := map[int]Person{
        1: {"Alice", 25},
        2: {"Bob", 30},
        3: {"Charlie", 35},
    }
    
    personList := slices.Values(people)
    fmt.Println("People:", personList)
}

该映射使用整数 ID 作为键,Person 结构体作为值。该函数返回所有 Person 对象的切片,忽略它们的映射键。

空映射行为

`slices.Values` 能妥善处理空映射。此示例显示当输入映射没有元素时,它会返回一个空切片。

empty_map.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    emptyMap := map[string]int{}
    
    values := slices.Values(emptyMap)
    fmt.Println("Values from empty map:", values)
    fmt.Println("Length:", len(values))
}

当给定一个空映射时,该函数会返回一个有效的空切片。此行为符合 Go 对空集合的约定。

修改返回的切片

`slices.Values` 返回的切片是一个新的副本。此示例演示了修改它不会影响原始映射。

modify_slice.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    scores := map[string]int{
        "Alice": 85,
        "Bob":   92,
        "Carol": 78,
    }
    
    scoreSlice := slices.Values(scores)
    scoreSlice[0] = 100
    
    fmt.Println("Modified slice:", scoreSlice)
    fmt.Println("Original map:", scores)
}

更改返回切片中的元素不会修改原始映射值。该函数创建一个包含映射值副本的新切片。

将值与其他函数一起使用

返回的切片可以与其他切片函数一起使用。此示例在从映射中提取值后对它们进行排序。

sort_values.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    temperatures := map[string]float64{
        "Monday":    72.5,
        "Tuesday":   68.3,
        "Wednesday": 75.1,
        "Thursday":  69.8,
    }
    
    tempValues := slices.Values(temperatures)
    slices.Sort(tempValues)
    
    fmt.Println("Sorted temperatures:", tempValues)
}

我们从映射中提取温度值并按升序排序。这展示了 `slices.Values` 如何支持切片操作。

性能注意事项

对于大型映射,`slices.Values` 会为新切片分配内存。此示例使用不同大小的映射对操作进行了基准测试。

performance.go
package main

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

func main() {
    smallMap := make(map[int]int, 100)
    largeMap := make(map[int]int, 1_000_000)
    
    for i := 0; i < 100; i++ {
        smallMap[i] = i
    }
    
    for i := 0; i < 1_000_000; i++ {
        largeMap[i] = i
    }
    
    start := time.Now()
    _ = slices.Values(smallMap)
    fmt.Println("Small map:", time.Since(start))
    
    start = time.Now()
    _ = slices.Values(largeMap)
    fmt.Println("Large map:", time.Since(start))
}

函数的执行时间与映射大小成线性关系。对于大型映射,内存分配是主要的成本因素。

实际应用:数据处理

这个实际示例处理存储在映射中的调查数据。我们提取值来计算统计数据。

data_processing.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    surveyResults := map[string]int{
        "Q1": 4, "Q2": 5, "Q3": 3,
        "Q4": 2, "Q5": 5, "Q6": 4,
    }
    
    ratings := slices.Values(surveyResults)
    
    total := 0
    for _, r := range ratings {
        total += r
    }
    
    average := float64(total) / float64(len(ratings))
    fmt.Printf("Average rating: %.2f\n", average)
}

我们从映射中提取调查评分来计算其平均值。这展示了 `slices.Values` 在数据分析中的实际用例。

来源

Go 实验性切片包文档

本教程通过各种场景中从映射中提取值的实际示例,介绍了 Go 中的 `slices.Values` 函数。

作者

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

列出所有 Go 教程