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
是並發安全的,為什麼這一行會產生這種恐慌,我該如何正確處理它? </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 中的並發安全範本:我該怎麼做?的詳細內容。更多資訊請關注PHP中文網其他相關文章!