Почему я вижу ZgotmplZ в выходных данных моего HTML-шаблона Go?

Когда я вызываю функцию шаблона Go для вывода HTML, она отображает ZgotmplZ.

Образец кода:

http://play.golang.org/p/tfuJa_pFkm

package main

import (
    "html/template"
    "os"
)

func main() {
    funcMap := template.FuncMap{
        "printSelected": func(s string) string {
            if s == "test" {
                return `selected="selected"`
            }
            return ""
        },

        "safe": func(s string) template.HTML {
            return template.HTML(s)
        },
    }
    template.Must(template.New("Template").Funcs(funcMap).Parse(`
    <option {{ printSelected "test" }} {{ printSelected "test" | safe }} >test</option>
    `)).Execute(os.Stdout, nil)

}

Выход:

<option ZgotmplZ ZgotmplZ >test</option>

person Randy Proctor    schedule 08.02.2013    source источник


Ответы (6)


«ZgotmplZ» — это специальное значение, указывающее, что небезопасное содержимое достигло контекста CSS или URL-адреса во время выполнения. Вывод примера будет:

 <img src="#ZgotmplZ">

Вы можете добавить функцию safe и attr в шаблон funcMap:

основной пакет

import (
    "html/template"
    "os"
)

func main() {
    funcMap := template.FuncMap{
        "attr":func(s string) template.HTMLAttr{
            return template.HTMLAttr(s)
        },
        "safe": func(s string) template.HTML {
            return template.HTML(s)
         },
    }

    template.Must(template.New("Template").Funcs(funcMap).Parse(`
    <option {{  .attr |attr }} >test</option>
        {{.html|safe}}
     `)).Execute(os.Stdout,   map[string]string{"attr":`selected="selected"`,"html":`<option selected="selected">option</option>`})
}

Вывод будет выглядеть так:

<option selected="selected" >test</option>
<option selected="selected">option</option>

Возможно, вы захотите определить некоторые другие функции, которые могут преобразовывать строку в template.CSS, template.JS, template.JSStr, template.URL и т. д.

person Joe    schedule 10.02.2013
comment
Это тоже не работает, FYI (для функции, которая принимает входные данные и использует их на выходе). - person Randy Proctor; 10.02.2013
comment
safe позволяет отображать необработанный html в шаблоне. - person Joe; 13.02.2013
comment
Используйте template.HTMLAttr вместо template.HTML, все работает нормально. см. обновленный код. - person Joe; 14.02.2013
comment
Это работает, спасибо. Продемонстрировано для потомков: play.golang.org/p/nq3-7GYAoY - person Randy Proctor; 15.02.2013
comment
функция iteral не нужна - person Nate Scarlet; 23.11.2019

У меня была аналогичная проблема с <img src="{{myfunction}}">, где моя функция возвращает закодированное изображение.

Наконец я решил это, когда вместо строки функция возвращает template.URL(mystring).

person Rio    schedule 18.10.2015

Вы пытаетесь вывести HTML в месте, где template/html считает небезопасным (например, внутри HTML-элемента, например:

<option {{ printSelected }}>

Я не могу найти способ убедить его в безопасности (включая возврат template.HTML вместо строки); единственная альтернатива, которую я нашел, - это переписать шаблон, в этом примере вместо этого используйте логический вывод:

<option {{ if printSelected }}selected{{ end }}>
person Randy Proctor    schedule 08.02.2013
comment
Лично я предпочитаю ваше предложение по простой причине: несмотря на все другие правильные ответы, ваш — хотя, возможно, и «более подробный», — является единственным, который гарантирует, что небезопасный контент никогда< /i> добраться до шаблона. Это, ИМХО, должно быть лучшим способом ведения дел. Любые уловки или хаки, основанные на «обмане» Go, чтобы принять потенциально небезопасный код… ну, небезопасно, не так ли? - person Gwyneth Llewelyn; 16.06.2020

Самый простой способ:

import "html/template"
yourhref = template.URL(yourhref)
person 陈小叶    schedule 25.01.2018
comment
Это правильный ответ, если вы хотите отображать текст в атрибуте href, например: <a href="{{.Host}}">Hi</a>, Host должен быть template.URL, чтобы избежать ZgotmplZ. - person wbsnail; 25.03.2021

package main

import (
    "html/template"
    "os"
)

type T struct {
    HTML template.HTML
    ATTR template.HTMLAttr
    URL  template.URL
    JS   template.JS
    CSS  template.CSS
}

func main() {

    data := T{
        HTML: `<div>test div</div>`,
        ATTR: `selected="selected"`,
        URL:  `https://upload.wikimedia.org/wikipedia/commons/5/53/Google_%22G%22_Logo.svg`,
        CSS:  `font-size: 15px`,
        JS:   `console.log("hello world")`,
    }

    template.Must(template.New("Template").Parse(`
        {{.HTML}}
        <option {{.ATTR}} style="{{.CSS}}">test</option>
        <script>{{.JS}}</script>
        <img src="{{.URL}}">
    `)).Execute(os.Stdout, data)
}

выход

<div>test div</div>
<option selected="selected" style="font-size: 15px">test</option>
<script>console.log("hello world")</script>
<img src="https://upload.wikimedia.org/wikipedia/commons/5/53/Google_%22G%22_Logo.svg">

Пример игровой площадки

person Isaac Weingarten    schedule 07.10.2019

Вы должны обернуть строку в HTMLAttr, который был разработан для текста, который вставляется между угловыми скобками. Согласно документации:

https://golang.org/pkg/html/template/#HTMLAttr

HTMLAttr инкапсулирует атрибут HTML из надежного источника, например,  dir="ltr".

Использование этого типа представляет угрозу безопасности: инкапсулированное содержимое должно поступать из надежного источника, так как оно будет дословно включено в выходные данные шаблона.

type HTMLAttr string

person Brandon Rhodes    schedule 12.06.2018