模板字符串和函数连接

问题描述

我尝试在 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))
}

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

解决方法

例如,

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,并且任何不寻常的字符都被正确转义,等等。