Go 对比 Python:Go 中有“if x in”结构吗?

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:为什么 Python 程序员在 Go 中怀念 "in"?

\n\n

如果您从 Python 世界来到 Go,您一定记得这个神奇的代码行:if "banana" in fruits:。简短、优雅、可读性强。然后您打开 Go 并问自己:"Go 是否有类似 Python 的 'if x in' 结构?" —— 这正是 Stack Overflow 上最流行的问题,获得了数千次浏览。

\n\n

剧透:Go 中没有像 in 这样的直接语法糖。但这并不意味着问题无法解决或解决起来很复杂。相反,Go 有几种惯用的方法来检查成员关系,每种方法都高效且各有特色。

\n\n

在本文中,我们将讨论:

\n
    \n
  • 为什么 Go 没有 in,以及语言哲学如何影响这一点;
  • \n
  • 如何检查切片中元素的存在(包括使用新函数 slices.Contains);
  • \n
  • 如何在映射中搜索(剧透:这是最快的方法);
  • \n
  • 通过 strings.Contains 在字符串中搜索子串;
  • \n
  • 编写我们自己的通用包装函数以实现“Python 风格”;
  • \n
  • 比较各种方法的性能。
  • \n
\n\n

为什么 Go 不想要 "if x in"?

\n\n

Go 是一种极简语言。它的创建者(Rob Pike、Ken Thompson、Rob Griesemer)有意识地避免使语法过载。他们没有添加关键字 in,而是建议使用显式循环和内置结构。

\n\n

这不是缺点,而是一个特点:您总是能看到正在发生的事情。例如,对于映射,语法 value, ok := myMap[key] 不仅为您提供了存在性检查,还提供了值本身——这比简单的布尔值 True/False 更强大。

\n\n

方法 1:在切片中搜索(经典方法)

\n\n

最常见的场景。假设您有一个字符串切片,需要检查其中是否有 "Go"。

\n\n

在 Go 1.21 版本之前,您必须手动编写循环:

\n\n
package main\n\nimport "fmt"\n\nfunc contains(slice []string, target string) bool {\n    for _, v := range slice {\n        if v == target {\n            return true\n        }\n    }\n    return false\n}\n\nfunc main() {\n    languages := []string{"Python", "Java", "Go", "Rust"}\n    if contains(languages, "Go") {\n        fmt.Println("Go 已找到!")\n    }\n}\n
\n\n

这段代码是地道的 Go 代码。它显式、快速且易于理解。对于小型切片(最多 1000 个元素),这种线性搜索效果很好。

\n\n

方法 1.1:使用 slices.Contains(Go 1.21+)

\n\n

从 Go 1.21 版本(于 2023 年 8 月发布)开始,标准库中引入了 slices 包,其中包含现成的 Contains 函数。现在您的代码几乎和 Python 一样简洁:

\n\n
package main\n\nimport (\n    "fmt"\n    "slices"\n)\n\nfunc main() {\n    languages := []string{"Python", "Java", "Go", "Rust"}\n    if slices.Contains(languages, "Go") {\n        fmt.Println("Go 已找到!(通过 slices.Contains)")\n    }\n}\n
\n\n

重要提示: slices.Contains 是一个泛型函数。它适用于任何支持 == 运算符的类型(字符串、数字、布尔值、不包含切片/映射的结构体)。

\n\n

方法 2:在映射中搜索——性能之王

\n\n

在 Python 中,您对字典使用 in,这是常数时间 O(1)。在 Go 中也是如此,但语法不同:

\n\n
package main\n\nimport "fmt"\n\nfunc main() {\n    // 创建映射作为集合\n    fruits := map[string]bool{\n        "apple":  true,\n        "banana": true,\n        "cherry": true,\n    }\n\n    if fruits["banana"] {\n        fmt.Println("banana 存在!")\n    }\n\n    // 更正确的方法——使用 ok 检查\n    if _, ok := fruits["orange"]; ok                

博客

书籍推荐