Jav*_*per 8 regex compilation instance-variables go
下面是我的 golang 代码。每次调用验证方法时,我的编译方法都会被执行。我只想编译一次,而不是每次调用验证时都编译。
1)怎么做?2)我的想法是创建一个实例变量,该变量在开始时为零。它会在验证中延迟初始化。
if (a != nil) {
a, err := regexp.Compile(rras.Cfg.WhiteList)
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我将变量声明为实例变量,
var a *Regexp; // regexp.Compile returns *Regexp
Run Code Online (Sandbox Code Playgroud)
我的编译器用红色下划线。如何修复它?
type RRAS struct {
Cfg *RRAPIConfig
}
type RRAPIConfig struct {
WhiteList string
}
func (rras *RRAS) validate(ctx context.Context) error {
a, err := regexp.Compile(rras.Cfg.WhiteList)
}
Run Code Online (Sandbox Code Playgroud)
var whitelistRegexp = regexp.MustCompile(Cfg.WhiteList)
func (rras *RRAS) validate(ctx context.Context) error {
if !whitelistRegexp.Match(...) {...}
}
Run Code Online (Sandbox Code Playgroud)
这将在包导入后立即编译正则表达式,这通常是在程序启动时,在主方法中的任何代码执行之前。
var whitelistR struct{
rex *regexp.Regexp
once sync.Once
err error
}
func (rras *RRAS) validate(ctx context.Context) error {
whitelistR.once.Do(func() {
whitelistR.ex, whitelistR.err = regexp.Compile(rras.Cfg.WhiteList)
})
if whitelistR.err != nil {
return fmt.Errorf("could not compile regex: %w", err)
}
if !whitelistR.rex.Match(...) {...}
}
Run Code Online (Sandbox Code Playgroud)
这将在第一次调用该方法时轻松编译正则表达式。非常sync.Once重要,因为它是一个同步点,保证对正则表达式的访问不会出现竞争条件。每次调用该方法都必须等到 Regexp 第一次编译。之后同步非常快,因为它仅使用原子加载。
您还可以go once.Do(...)在 main 方法中调用并行初始化正则表达式,以加快第一次调用的速度,而不会阻塞其他方法。
几乎总是使用简单的静态初始化。仅当您确定对性能有影响(基准测试)时,才使用同步初始化。同步访问时,始终尝试使用 go 提供的帮助程序(sync.Once、Mutex、RWMutex 等),因为它们经过优化且不易出错。
Go 内存模型详细介绍了同步和最佳实践
Go Data Race Detector你应该对每个复杂的多例程 go 程序进行竞赛测试