Go 中的并发安全模板:我该怎么做?
Go 中的并发安全模板是一个关键问题,对于需要在并发环境下进行操作的程序来说,确保数据的安全性是至关重要的。在处理并发时,我们需要采取一些措施来保护共享资源,避免出现竞态条件和数据竞争。在这篇文章中,我将向大家介绍一些常用的并发安全模板,帮助你理解并发安全的概念,并提供一些实践中的建议。无论是初学者还是有经验的开发者,都可以从中受益。让我们一起来探讨如何在 Go 中实现并发安全!
问题内容
我有以下电话:
import (
"text/template"
)
//...
template.new(filepath.base(name)).funcs(templatefunctions).parse(string(asset))
在多个 go 例程中同时调用, 这又会导致以下恐慌:
fatal error: concurrent map iteration and map write
这是回溯:
goroutine 140 [running]:
text/template.addvaluefuncs(0xc00188e000?, 0xc00188e000?)
[...]/go/class="lazy" data-src/text/template/funcs.go:88 +0x76
[...]/modules/template.loadembeddedtemplates({0x38ff6cb?, 0xc001cf8060?})
[...]/class="lazy" data-src/modules/template/configbased.go:163 +0x749
class="lazy" data-src/modules/template/configbased.go:163
上的行
上面引用了。它是 template.new(...)
。
周围的函数是从 goroutine 中同时调用的。
这是来自 go/class="lazy" data-src/text/template/funcs.go:88
的代码是否有帮助:
// addvaluefuncs adds to values the functions in funcs, converting them to reflect.values.
func addvaluefuncs(out map[string]reflect.value, in funcmap) {
for name, fn := range in {
if !goodname(name) {
panic(fmt.errorf("function name %q is not a valid identifier", name))
}
v := reflect.valueof(fn)
if v.kind() != reflect.func {
panic("value for " + name + " not a function")
}
if !goodfunc(v.type()) {
panic(fmt.errorf("can't install method/function %q with %d results", name, v.type().numout()))
}
out[name] = v
}
}
如果 template.new
是并发安全的,为什么这一行会产生这种恐慌,我应该如何正确处理它?</p>
更新。
令人讨厌的函数loadembeddedtemplates
的代码:
func loadEmbeddedTemplates(templateFile string) (*template.Template, error) {
var t *template.Template
templateFile = filepath.Join("share", "templates", filepath.Base(templateFile))
dir := filepath.Dir(templateFile)
names := assets.GetAssetNames()
// All templates except + the last one at the end
filteredNames := []string{}
for _, name := range names {
if !strings.HasPrefix(name, dir+"/") || !strings.HasSuffix(name, ".tmpl") {
continue
}
if name != templateFile {
filteredNames = append(filteredNames, name)
}
}
filteredNames = append(filteredNames, templateFile)
for _, name := range filteredNames {
asset, err := assets.GetAsset(name)
if err != nil {
return nil, err
}
if t == nil {
t, err = template.New(filepath.Base(name)).Funcs(templateFunctions).Parse(string(asset))
} else {
t, err = t.New(filepath.Base(name)).Parse(string(asset))
}
if err != nil {
return nil, err
}
}
return t, nil
}
该函数只是依次加载 share/templates/
中的所有模板
解决方法
您的 loadEmbeddedTemplates()
函数访问 templateFunctions
变量,将其传递给 Template.Funcs()
,后者显然会读取它(将迭代它)。
并且您可能会在另一个 goroutine 中同时填充它。因此,并发映射写入错误。对它的访问必须同步。
如果可能,请先填充它,然后才开始使用它(将其传递给 Template.Funcs()
)。这样就不需要额外的同步或锁定(并发只读总是可以的)。
以上就是Go 中的并发安全模板:我该怎么做?的详细内容,更多请关注编程网其它相关文章!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341