Concurrency-safe templates in Go: How do I do it?

WBOY
Release: 2024-02-08 21:50:10
forward
955 people have browsed it

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

Concurrency safety templates in Go are a key issue. For programs that need to operate in a concurrent environment, ensuring the security of data is crucial. When dealing with concurrency, we need to take some measures to protect shared resources and avoid race conditions and data races. In this article, I will introduce you to some commonly used concurrency safety templates, help you understand the concept of concurrency safety, and provide some practical suggestions. Both beginners and experienced developers can benefit from it. Let’s explore how to achieve concurrency safety in Go!

Question content

I have the following phone number:

import (
  "text/template"
)

//...

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

Called simultaneously in multiple go routines, This in turn leads to the following panic:

fatal error: concurrent map iteration and map write
Copy after login

This is the 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
Copy after login
The line at

src/modules/template/configbased.go:163 quoted above. It is template.new(...).

The surrounding functions are called simultaneously from goroutine.

Here is the code from go/src/text/template/funcs.go:88 If it helps:

// 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
    }
}
Copy after login

If template.new is concurrency safe, why does this line generate this panic and how should I handle it correctly? <​​/p>

renew.

Code of

annoying functionloadembeddedtemplates:

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
}
Copy after login

This function just loads all templates in share/templates/ in sequence

Solution

Your loadEmbeddedTemplates() Function accesstemplateFunctions variable, pass it to Template.Funcs() which will obviously read it (will iterate over it).

And you might populate it in another goroutine at the same time. Hence the concurrent map write error. Access to it must be synchronized.

If possible, populate it before starting to use it (pass it to Template.Funcs()). This way no additional synchronization or locking is required (concurrent read-only is always possible).

The above is the detailed content of Concurrency-safe templates in Go: How do I do it?. For more information, please follow other related articles on the PHP Chinese website!

source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template