首页 > 解决方案 > 模板字符串和函数连接

问题描述

我尝试在 go 函数中对一些 JSON 值进行模板化,这基本上像我期望的那样工作。但是,如果我尝试将模板字符串与模板函数连接起来,它会失败(有不同的错误,取决于模板字符串的外观)

例如,我有以下行:

{"APPLICATION_HOST":"http://{{ .NAMESPACE }}-repo.{{ .NAMESPACE }}:3004"}

模板工作并给出以下输出:

{"APPLICATION_HOST":"http://test-repo.test:3004"}

我现在想用 base64 对值进行编码,并尝试了以下示例:

{"APPLICATION_HOST":"{{ http://{{ .NAMESPACE }}-repo.{{ .NAMESPACE }}:3004 | b64encode }}"}

这给出了错误:

“http://”不是函数

如果我只是执行以下操作(看起来很可怕):

{"APPLICATION_HOST":"{{ printf "http://{{ .NAMESPACE }}-repo.{{ .NAMESPACE }}:3004"|b64encode }}"}

它输出以下内容:

{"APPLICATION_HOST":"aHR0cDovL3t7IC5OQU1FU1BBQ0UgfX0tcmVwby57eyAuTkFNRVNQQUNFIH19OjMwMDQ="}

什么解码为:

http://{{ .NAMESPACE }}-repo.{{ .NAMESPACE }}:3004

模板函数目前看起来像这样:

func generateDefinitionJson(filePath string, bodyBytes []byte) (interface{}, error) {
    var (
        tpl             bytes.Buffer
        err             error
        tplInterface, m map[string]interface{}
    )
    funcMap := template.FuncMap{
        // The name "b64encode" is what the function will be called in the template text.
        "b64encode": b64encode,
  }
    // read definition file
    fileContent, err := ioutil.ReadFile(filePath)
    // load definition as template
    t, err := template.New("").Funcs(funcMap).Parse(string(fileContent))
    if err != nil {
        logger.Error("Parsing Template failed: " + err.Error())
    } else {
        // create value map
        err = json.Unmarshal([]byte(bodyEscaped), &m)
        mInterfaceStr := fmt.Sprintf("%v", m)
        if err != nil {
            logger.Error("Failed to create Value Map: " + err.Error())
        } else {
            // execute template mapping
            err = t.Execute(&tpl, m)
            logger.Debug(tpl.String())
            if err != nil {
                logger.Error("Templating failed: " + err.Error())
            }
            // unmarshal template into interface
            err = json.Unmarshal([]byte(tpl.String()), &tplInterface)
            if err != nil {
                logger.Error("Couldn't Unmarshal definition to interface: " + err.Error())
            }
        }
    }
    return tplInterface, err
}

func b64encode(str string) string {
    return base64.StdEncoding.EncodeToString([]byte(str))
}

有谁知道如何解决这个问题?

标签: jsongogo-templates

解决方案


printf{{ .NAMESPACE }}例如,不做模板扩展。相反,它扩展%s和相关的动词。这意味着

{"APPLICATION_HOST":"{{ printf "http://{{ .NAMESPACE }}-repo.{{ .NAMESPACE }}:3004"|b64encode }}"}

应该

{"APPLICATION_HOST":"{{ printf "http://%s-repo.%s:3004" .NAMESPACE .NAMESPACE |b64encode }}"}

正确的答案是改用正确的 JSON 封送处理,这样您就可以确定生成了有效的 JSON,并且任何不寻常的字符都被正确转义,等等。


推荐阅读