ZetCode

Golang slices.DeleteFunc

最后修改于 2025 年 4 月 20 日

本教程将介绍如何在 Go 中使用 slices.DeleteFunc 函数。我们将通过实际删除元素的示例来讲解切片操作。

slices.DeleteFunc 函数会从切片中移除满足给定条件的元素。它是 Go 实验性 slices 包的一部分。

此函数可用于过滤数据或从集合中移除不需要的元素。它会就地修改切片并返回修改后的切片。

基本的 slices.DeleteFunc 示例

slices.DeleteFunc 最简单的用法是移除切片中的所有负数。我们定义一个测试函数来识别要删除的元素。

basic_delete.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    numbers := []int{1, -2, 3, -4, 5}
    
    numbers = slices.DeleteFunc(numbers, func(n int) bool {
        return n < 0
    })
    
    fmt.Println("Positive numbers:", numbers)
}

我们创建一个包含正数和负数的切片。该函数会移除所有满足条件 (n < 0) 的元素。

删除空字符串

slices.DeleteFunc 可以从切片中过滤掉空字符串。此示例将删除所有空字符串或仅包含空格的字符串。

empty_strings.go
package main

import (
    "fmt"
    "slices"
    "strings"
)

func main() {
    words := []string{"apple", "", "banana", "  ", "cherry"}
    
    words = slices.DeleteFunc(words, func(s string) bool {
        return strings.TrimSpace(s) == ""
    })
    
    fmt.Println("Non-empty words:", words)
}

测试函数使用 strings.TrimSpace 来处理空格。修改后的切片仅包含非空字符串。

使用结构体

我们可以将 slices.DeleteFunc 与自定义结构体类型一起使用。此示例将从切片中移除所有不活跃的用户。

struct_delete.go
package main

import (
    "fmt"
    "slices"
)

type User struct {
    Name   string
    Active bool
}

func main() {
    users := []User{
        {"Alice", true},
        {"Bob", false},
        {"Charlie", true},
    }
    
    users = slices.DeleteFunc(users, func(u User) bool {
        return !u.Active
    })
    
    fmt.Println("Active users:", users)
}

该函数会检查每个用户的 `Active` 字段。Bob 会被从切片中移除,因为他的 `Active` 状态为 `false`。

删除重复元素

我们可以将 slices.DeleteFunc 与 map 结合使用来删除重复项。此示例仅保留每个唯一数字的第一次出现。

remove_duplicates.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    numbers := []int{1, 2, 2, 3, 4, 4, 4, 5}
    seen := make(map[int]bool)
    
    numbers = slices.DeleteFunc(numbers, func(n int) bool {
        if seen[n] {
            return true
        }
        seen[n] = true
        return false
    })
    
    fmt.Println("Unique numbers:", numbers)
}

map 会跟踪已看到的数字,并删除后续的重复项。结果中每个数字只出现一次。

不区分大小写的字符串过滤

此示例演示了如何使用 slices.DeleteFunc 进行不区分大小写的过滤。我们将移除所有 "apple" 的出现。

case_insensitive.go
package main

import (
    "fmt"
    "slices"
    "strings"
)

func main() {
    fruits := []string{"Apple", "banana", "APPLE", "cherry", "apple"}
    
    fruits = slices.DeleteFunc(fruits, func(s string) bool {
        return strings.EqualFold(s, "apple")
    })
    
    fmt.Println("Filtered fruits:", fruits)
}

strings.EqualFold 执行不区分大小写的比较。所有形式的 "apple" 都将被移除,而不考虑其大小写。

性能注意事项

对于大型切片,测试函数的性能至关重要。本示例将比较不同的过滤方法。

performance.go
package main

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

func main() {
    largeSlice := make([]int, 1_000_000)
    for i := range largeSlice {
        largeSlice[i] = i % 10 // Create repeating pattern
    }
    
    // Simple condition
    start := time.Now()
    _ = slices.DeleteFunc(largeSlice, func(n int) bool {
        return n == 5
    })
    fmt.Println("Simple condition:", time.Since(start))
    
    // Complex condition
    start = time.Now()
    _ = slices.DeleteFunc(largeSlice, func(n int) bool {
        return n > 5 && n % 2 == 0
    })
    fmt.Println("Complex condition:", time.Since(start))
}

执行时间取决于条件的复杂性和删除的数量。slices.DeleteFunc 由于就地修改切片而效率很高。

实际示例:输入清理

此实际示例使用 slices.DeleteFunc 清理用户输入,移除无效条目。

input_sanitization.go
package main

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

func main() {
    inputs := []string{"42", "invalid", "15", "99", "not_a_number"}
    
    // First convert to numbers, tracking valid entries
    numbers := make([]int, 0, len(inputs))
    valid := make([]bool, len(inputs))
    
    for i, s := range inputs {
        num, err := strconv.Atoi(s)
        if err == nil {
            numbers = append(numbers, num)
            valid[i] = true
        }
    }
    
    // Now filter the original slice
    inputs = slices.DeleteFunc(inputs, func(s string) bool {
        _, err := strconv.Atoi(s)
        return err != nil
    })
    
    fmt.Println("Valid numbers:", numbers)
    fmt.Println("Sanitized inputs:", inputs)
}

我们首先识别无效条目,然后使用 slices.DeleteFunc 移除它们。这展示了实际的数据清理过程。

来源

Go 实验性切片包文档

本教程通过各种场景下过滤切片元素的实际示例,介绍了 Go 中的 slices.DeleteFunc 函数。

作者

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

列出所有 Go 教程