Golang中避免每次函数调用都重新编译正则表达式

Golang中避免每次函数调用都重新编译正则表达式 为了更清晰地说明问题,这里稍微简化一下:假设我需要一个函数,用于从字符串中提取非单词字符,并为此使用正则表达式。代码可能如下所示:

func essence(s string) string {
	re := regexp.MustCompile(`\W`)
	n := strings.ToLower(re.ReplaceAllString(s, ""))
	return n
}

我的理解是否正确,即每次调用该函数时,re 都会被重复编译?这(至少对于更复杂的正则表达式来说)代价会很高。

优秀的开发者会在哪里定义 re 呢? 在 main() 中? 在包级别(即在 main() 之前)? 闭包的概念对此有帮助吗?(我在这方面经验不足。)

我知道实现方式不止一种,但哪种方法既优雅又最易于维护呢?

感谢任何高明的建议。


更多关于Golang中避免每次函数调用都重新编译正则表达式的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

非常感谢;同时也感谢附带进行的测试/基准测试。

我知道,即使使用更复杂的正则表达式并多次调用我的函数,也不会对整体性能产生严重影响,但由于我更倾向于保持代码的一致性和整洁性,我将避免反复编译正则表达式,而是将其设为包内的全局变量。

目前我在考虑,将这样的正则表达式设为(包)常量是否有意义……

更多关于Golang中避免每次函数调用都重新编译正则表达式的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go中,正则表达式编译确实有开销,应该避免重复编译。以下是几种推荐的做法:

1. 包级变量(最常用)

var (
    re = regexp.MustCompile(`\W`)
)

func essence(s string) string {
    n := strings.ToLower(re.ReplaceAllString(s, ""))
    return n
}

2. 使用sync.Once实现延迟初始化

var (
    re     *regexp.Regexp
    reOnce sync.Once
)

func essence(s string) string {
    reOnce.Do(func() {
        re = regexp.MustCompile(`\W`)
    })
    n := strings.ToLower(re.ReplaceAllString(s, ""))
    return n
}

3. 闭包方式

func makeEssence() func(string) string {
    re := regexp.MustCompile(`\W`)
    return func(s string) string {
        n := strings.ToLower(re.ReplaceAllString(s, ""))
        return n
    }
}

// 使用
var essence = makeEssence()

4. 结构体封装

type Processor struct {
    re *regexp.Regexp
}

func NewProcessor() *Processor {
    return &Processor{
        re: regexp.MustCompile(`\W`),
    }
}

func (p *Processor) Essence(s string) string {
    n := strings.ToLower(p.re.ReplaceAllString(s, ""))
    return n
}

对于你的场景,包级变量是最简单直接的方式。如果正则表达式复杂且只在特定条件下使用,可以考虑sync.Once。闭包和结构体方式在需要状态隔离或配置时更有用。

实际项目中,包级变量是最常见的做法:

package main

import (
    "regexp"
    "strings"
)

var nonWordRegex = regexp.MustCompile(`\W`)

func essence(s string) string {
    cleaned := nonWordRegex.ReplaceAllString(s, "")
    return strings.ToLower(cleaned)
}
回到顶部