Templat selamat selaras dalam Go: Bagaimanakah caranya?

WBOY
Lepaskan: 2024-02-08 21:50:10
ke hadapan
956 orang telah melayarinya

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))
Salin selepas log masuk

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

fatal error: concurrent map iteration and map write
Salin selepas log masuk

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
Salin selepas log masuk

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
    }
}
Salin selepas log masuk

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

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
}
Salin selepas log masuk

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!

sumber:stackoverflow.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan