Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Templat selamat selaras dalam Go: Bagaimanakah caranya?

Templat selamat selaras dalam Go: Bagaimanakah caranya?

WBOY
WBOYke hadapan
2024-02-08 21:50:10946semak imbas

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

Templat keselamatan Concurrency dalam Go ialah isu utama Untuk program yang perlu beroperasi dalam persekitaran serentak, memastikan keselamatan data adalah penting. Apabila berurusan dengan konkurensi, kita perlu mengambil beberapa langkah untuk melindungi sumber yang dikongsi dan mengelakkan keadaan perlumbaan dan perlumbaan data. Dalam artikel ini, saya akan memperkenalkan anda kepada beberapa templat keselamatan serentak yang biasa digunakan, membantu anda memahami konsep keselamatan serentak dan memberikan beberapa cadangan praktikal. Kedua-dua pemula dan pembangun berpengalaman boleh mendapat manfaat daripadanya. Mari terokai cara untuk mencapai keselamatan serentak dalam Go!

Kandungan soalan

Saya ada nombor telefon berikut:

import (
  "text/template"
)

//...

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

Panggil serentak dalam pelbagai rutin pergi, Ini seterusnya membawa kepada panik berikut:

fatal error: concurrent map iteration and map write

Ini adalah jejak semula:

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 talian dihidupkan dipetik di atas. Ia adalah template.new(...).

Fungsi sekeliling dipanggil serentak dari goroutine.

Berikut ialah kod daripada go/src/text/template/funcs.go:88 Jika ia membantu:

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

Jika template.new concurrency selamat, mengapa talian ini menjana panik ini dan bagaimana saya harus mengendalikannya dengan betul?

Dikemas kini.

Kod untuk fungsi yang menjengkelkanloadembeddedtemplates:

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
}

Fungsi ini hanya memuatkan semua templat dalam share/templates/ dalam urutan share/templates/ 中的所有模板

解决方法

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

Workaround

Fungsi loadEmbeddedTemplates() anda mengakses pembolehubah templateFunctions , menghantarnya kepada

yang jelas akan membacanya (akan berulang di atasnya). Template.Funcs()

Dan anda mungkin mengisinya dalam goroutine lain pada masa yang sama. Oleh itu ralat tulis peta serentak. Akses kepadanya mesti disegerakkan. 🎜 🎜Jika boleh, isikan ia sebelum mula menggunakannya (luluskan kepada 🎜). Dengan cara ini tiada penyegerakan atau penguncian tambahan diperlukan (baca sahaja serentak sentiasa boleh dilakukan). 🎜

Atas ialah kandungan terperinci Templat selamat selaras dalam Go: Bagaimanakah caranya?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam