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/src/text/template/funcs.go:88 +0x76[...]/modules/template.loadembeddedtemplates({0x38ff6cb?, 0xc001cf8060?}) [...]/src/modules/template/configbased.go:163 +0x749
登录后复制
src/modules/template/configbased.go:163 上的行上面引用了。它是 template.new(…)。
周围的函数是从 goroutine 中同时调用的。
这是来自 go/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 是并发安全的,为什么这一行会产生这种恐慌,我应该如何正确处理它?
更新。
令人讨厌的函数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 中的并发安全模板:我该怎么做?的详细内容,更多请关注【创想鸟】其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。
发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2358987.html