ZetCode

Golang slices.Reverse

最后修改于 2025 年 4 月 20 日

本教程将介绍如何在 Go 中使用 slices.Reverse 函数。我们将通过实际示例涵盖切片反转操作。

slices.Reverse 函数会反转切片中元素的顺序。它是 Go 1.21 中引入的实验性 slices 包的一部分。

此函数会就地修改原始切片,而不是创建新切片。它可以与任何切片类型一起使用,并通过泛型来维护类型安全。

基本的 slices.Reverse 示例

slices.Reverse 最简单的用法是反转整数切片。该函数直接修改原始切片。

basic_reverse.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    numbers := []int{1, 2, 3, 4, 5}
    slices.Reverse(numbers)
    
    fmt.Println("Reversed numbers:", numbers)
}

我们创建一个数字切片并反转它们的顺序。输出显示了元素顺序颠倒的修改后的切片。

反转字符串切片

slices.Reverse 也适用于字符串切片。此示例反转姓名列表。

string_reverse.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    names := []string{"Alice", "Bob", "Charlie", "Diana"}
    slices.Reverse(names)
    
    fmt.Println("Reversed names:", names)
}

字符串切片是就地反转的,第一个元素变成最后一个。该操作保持所有字符串值不变。

反转结构体切片

我们可以反转自定义结构体类型的切片。此示例反转 Person 结构体切片。

struct_reverse.go
package main

import (
    "fmt"
    "slices"
)

type Person struct {
    Name string
    Age  int
}

func main() {
    people := []Person{
        {"Alice", 25},
        {"Bob", 30},
        {"Charlie", 17},
    }
    
    slices.Reverse(people)
    fmt.Println("Reversed people:", people)
}

结构体切片在保持所有字段值不变的情况下被反转。每个 Person 结构体都保持完整,只有它们的顺序发生变化。

空切片和单元素切片

slices.Reverse 能很好地处理边缘情况。此示例显示了空切片和单元素切片的行为。

edge_cases.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    empty := []int{}
    single := []string{"alone"}
    
    slices.Reverse(empty)
    slices.Reverse(single)
    
    fmt.Println("Empty:", empty)
    fmt.Println("Single:", single)
}

反转空切片或单元素切片没有明显效果。操作会完成,但不会更改切片内容。

保留原始切片

要保持原始切片不变,请在反转之前创建一个副本。此示例演示了这两种方法。

preserve_original.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    original := []int{10, 20, 30, 40}
    
    // Modifies original
    slices.Reverse(original)
    fmt.Println("Modified original:", original)
    
    // Preserve original with copy
    preserved := []int{10, 20, 30, 40}
    copy := slices.Clone(preserved)
    slices.Reverse(copy)
    
    fmt.Println("Original:", preserved)
    fmt.Println("Reversed copy:", copy)
}

我们展示了直接修改和复制后反转的方法。slices.Clone 函数有助于保留原始数据。

性能注意事项

对于大型切片,反转可能会占用大量内存。此示例将对不同大小的切片进行操作的基准测试。

performance.go
package main

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

func main() {
    sizes := []int{1_000, 10_000, 100_000, 1_000_000}
    
    for _, size := range sizes {
        slice := make([]int, size)
        for i := range slice {
            slice[i] = i
        }
        
        start := time.Now()
        slices.Reverse(slice)
        elapsed := time.Since(start)
        
        fmt.Printf("Size %d: %v\n", size, elapsed)
    }
}

基准测试显示了执行时间如何随切片大小而变化。反转是一个 O(n) 操作,它交换 n/2 个元素。

实际示例:回文检查

这个实际示例使用 slices.Reverse 来检查一个字符串是否是回文(正读和反读都一样)。

palindrome.go
package main

import (
    "fmt"
    "slices"
)

func isPalindrome(s string) bool {
    runes := []rune(s)
    reversed := slices.Clone(runes)
    slices.Reverse(reversed)
    
    return slices.Equal(runes, reversed)
}

func main() {
    tests := []string{"radar", "hello", "madam", "golang"}
    
    for _, word := range tests {
        fmt.Printf("%s: %t\n", word, isPalindrome(word))
    }
}

我们将字符串转换为 rune,创建一个反转的副本,然后进行比较。这演示了切片反转的实际用途。

来源

Go 实验性切片包文档

本教程通过实际示例,介绍了 Go 中的 slices.Reverse 函数,以及在各种场景下反转切片元素的用法。

作者

我叫 Jan Bodnar,是一位充满激情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。到目前为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出所有 Go 教程