Heim  >  Artikel  >  Backend-Entwicklung  >  Parallelitätssichere Vorlagen in Go: Wie mache ich das?

Parallelitätssichere Vorlagen in Go: Wie mache ich das?

WBOY
WBOYnach vorne
2024-02-08 21:50:10946Durchsuche

Go 中的并发安全模板:我该怎么做?

Parallelitätssicherheitsvorlagen in Go sind ein zentrales Thema. Für Programme, die in einer gleichzeitigen Umgebung ausgeführt werden müssen, ist die Gewährleistung der Datensicherheit von entscheidender Bedeutung. Beim Umgang mit Parallelität müssen wir einige Maßnahmen ergreifen, um gemeinsam genutzte Ressourcen zu schützen und Rennbedingungen und Datenwettläufe zu vermeiden. In diesem Artikel stelle ich Ihnen einige häufig verwendete Vorlagen für Parallelitätssicherheit vor, helfe Ihnen, das Konzept der Parallelitätssicherheit zu verstehen, und gebe einige praktische Vorschläge. Sowohl Anfänger als auch erfahrene Entwickler können davon profitieren. Lassen Sie uns untersuchen, wie Sie in Go! Parallelitätssicherheit erreichen können!

Frageinhalt

Ich habe folgende Telefonnummer:

import (
  "text/template"
)

//...

template.new(filepath.base(name)).funcs(templatefunctions).parse(string(asset))

Gleichzeitig in mehreren Go-Routinen anrufen, Dies wiederum führt zu folgender Panik:

fatal error: concurrent map iteration and map write

Das ist der Traceback:

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 Zeilen an oben zitiert. Es ist template.new(...).

Die umgebenden Funktionen werden gleichzeitig von der Goroutine aufgerufen.

Hier ist der Code von go/src/text/template/funcs.go:88 Wenn es hilft:

// 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
    }
}

Wenn template.new parallelitätssicher ist, warum erzeugt diese Zeile dann diese Panik und wie sollte ich richtig damit umgehen?

Aktualisiert.

Code für die nervige Funktionloadembeddedtemplates:

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
}

Diese Funktion lädt einfach alle Vorlagen in share/templates/ nacheinander. share/templates/ 中的所有模板

解决方法

您的 loadEmbeddedTemplates() 函数访问 templateFunctions 变量,将其传递给 Template.Funcs()

Problemumgehung

Ihre Funktion loadEmbeddedTemplates() greift auf die Variable templateFunctions zu. Übergeben Sie es an

, das es offensichtlich liest (wird darüber iterieren). Template.Funcs()

Und Sie könnten es gleichzeitig in einer anderen Goroutine auffüllen. Daher der Fehler beim gleichzeitigen Schreiben der Karte. Der Zugriff darauf muss synchronisiert werden. 🎜 🎜Wenn möglich, füllen Sie es aus, bevor Sie es verwenden (geben Sie es an 🎜 weiter). Auf diese Weise ist keine zusätzliche Synchronisierung oder Sperrung erforderlich (gleichzeitiges Nur-Lesen ist immer möglich). 🎜

Das obige ist der detaillierte Inhalt vonParallelitätssichere Vorlagen in Go: Wie mache ich das?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen