ZetCode

Golang regexp.MustCompile

最后修改于 2025 年 4 月 20 日

本教程将解释如何在 Go 中使用 regexp.MustCompile 函数。我们将涵盖正则表达式基础知识并提供实际示例。

一个 正则表达式 是一个定义搜索模式的字符序列。它用于字符串中的模式匹配。

regexp.MustCompile 函数将正则表达式模式编译成一个可重用的 Regexp 对象。如果模式无效,它会 panic。

基本的 regexp.MustCompile 示例

regexp.MustCompile 最简单的用法是检查字符串是否匹配某个模式。这里我们检查一个简单的单词匹配。

basic_match.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`hello`)
    
    fmt.Println(re.MatchString("hello there")) // true
    fmt.Println(re.MatchString("goodbye"))     // false
}

我们使用 MustCompile 编译模式 "hello",并使用 MatchString 测试字符串。如果找到模式,该函数返回 true。

验证电子邮件地址

一个常见的用例是验证电子邮件地址。本例展示了一个使用 MustCompile 的基本电子邮件模式匹配器。

email_match.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    pattern := `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`
    re := regexp.MustCompile(pattern)

    emails := []string{
        "user@example.com",
        "invalid.email",
        "another.user@domain.co.uk",
    }

    for _, email := range emails {
        if re.MatchString(email) {
            fmt.Printf("%s is valid\n", email)
        } else {
            fmt.Printf("%s is invalid\n", email)
        }
    }
}

该模式匹配标准的电子邮件格式。请注意,与 Compile 不同,MustCompile 在模式无效时会 panic。

提取子匹配项

regexp.MustCompile 可以提取匹配字符串的部分。这里我们从格式化的字符串中提取日期组件。

submatches.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`(\d{4})-(\d{2})-(\d{2})`)
    date := "2025-04-20"

    matches := re.FindStringSubmatch(date)
    if matches != nil {
        fmt.Println("Year:", matches[1])
        fmt.Println("Month:", matches[2])
        fmt.Println("Day:", matches[3])
    }
}

我们使用括号创建捕获组。FindStringSubmatch 返回所有匹配项,完整匹配项位于索引 0,分组项在其后。

使用 Regex 替换文本

编译后的 regex 模式可用于搜索和替换操作。本例演示了简单的文本替换。

replace.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`\b(\w+)\s+\1\b`)
    text := "This is is a test test sentence."

    result := re.ReplaceAllString(text, "$1")
    fmt.Println(result)
}

该模式查找连续重复的单词。替换操作使用反向引用 $1,只保留每个重复单词的一个实例。

使用 Regex 分割字符串

strings.Split 相比,Regex 模式可以更灵活地分割字符串。这里我们在多个分隔符上进行分割。

split.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`[,;]\s*`)
    text := "apple,banana; cherry,  date;elderberry"

    parts := re.Split(text, -1)
    for _, part := range parts {
        fmt.Println(part)
    }
}

该模式匹配逗号或分号,后面可以跟可选的空格。Split 在每个匹配处分割字符串。

MustCompile 与 Compile

Go 提供了两个编译函数。MustCompile 在模式无效时 panic,而 Compile 返回一个错误。

must_vs_regular.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    // Safe with MustCompile when pattern is known good
    re1 := regexp.MustCompile(`valid`)
    fmt.Println(re1.MatchString("valid pattern"))

    // Compile is safer for dynamic patterns
    re2, err := regexp.Compile(`valid`)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println(re2.MatchString("valid pattern"))
}

对于编译时已知的静态模式,推荐使用 MustCompile。当处理用户提供的模式时,使用 Compile

全局 Regexp 对象

为了获得更好的性能,请一次性编译 regex 模式并重复使用它们。全局变量非常适合此目的。

global_regex.go
package main

import (
    "fmt"
    "regexp"
)

var dateRe = regexp.MustCompile(`(\d{4})-(\d{2})-(\d{2})`)

func main() {
    dates := []string{
        "2025-04-20",
        "2023-12-25",
        "invalid-date",
    }

    for _, date := range dates {
        if dateRe.MatchString(date) {
            fmt.Printf("%s is valid\n", date)
        } else {
            fmt.Printf("%s is invalid\n", date)
        }
    }
}

全局 dateRe 在程序启动时编译一次。这避免了每次函数调用时重新编译模式。

来源

Go regexp 包文档

本教程通过实际的模式匹配和文本操作示例,涵盖了 Go 中的 regexp.MustCompile 函数。

作者

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

列出所有 Go 教程