我有一个结构,其url.URL
值是其(多个)字段之一。我正在尝试将该结构的实例传递给html/template
并让它以合理的方式呈现这些字段,包括URL。
考虑这个示例代码:
package main
import (
"html/template"
"net/url"
"os"
)
var tmpl *template.Template = template.Must(
template.New("").Parse(`<a href="{{ .URL }}">{{ .Text }}</a>` + "\n"),
)
type pointer struct {
Text string
URL *url.URL // pointer, which is rendered sensibly
}
type value struct {
Text string
URL url.URL // value, which is not rendered sensibly
}
func main() {
u := url.URL{Scheme: "https", Host: "google.com", Path: "/path"}
pointer := pointer{Text: "pointer", URL: &u}
value := value{Text: "value", URL: u}
tmpl.Execute(os.Stdout, pointer)
tmpl.Execute(os.Stdout, value)
}
在我的机器上(去1.9.1),输出:
<a href="https://google.com/path">pointer</a>
<a href="%7bhttps%20%20%3cnil%3e%20google.com%20/path%20%20false%20%20%7d">value</a>
在the playground上,输出:
<a href="https://google.com/path">pointer</a>
<a href="
** Signal 11 from untrusted code: pc=630b0008b020
Program exited.
让html/template
呈现url.URL
值的最佳方式是什么?这是传递结构“通常”的字段?
(理想情况下,我只会更改模板,或者可能在FuncMap
中使用某些内容。我还希望避免创建一堆几乎相同的结构{{1} } s而不是*url.URL
s,或者必须使用struct的字段填充地图并将 传递给模板。)
答案 0 :(得分:3)
问题是模板引擎不会使用值的地址来查找String() string
方法。
一种解决方法是使用FuncMap:
func urlstr(u url.URL) string {
return u.String()
}
var tmpl *template.Template = template.Must(
template.New("").Funcs(template.FuncMap{"urlstr": urlstr}).Parse(`<a href="{{urlstr .URL}}">{{ .Text }}</a>` + "\n"),
)
请注意,在调用u
时,编译器会隐式使用String() string
的地址。
如果您混合使用*url.URL
和url.URL
值,并且不想担心模板中包含哪种类型,请将上面的函数urlstr
替换为:< / p>
func urlstr(u interface{}) string {
switch u := u.(type) {
case *url.URL:
return u.String()
case url.URL:
return u.String()
default:
panic("unexpected")
}
}
答案 1 :(得分:-1)
看起来像带有url.URL值的func的FuncMap会这样做:
func f(u url.URL) string {
return fmt.Sprintf("%s-%s-%s", u.Scheme, u.Host, u.Path)
}
和
funcMap := template.FuncMap{
"url": f,
}
var tmpl *template.Template = template.Must(
template.New("").Funcs(funcMap).Parse(`<a href="{{ url .URL }}">{{ .Text }}</a>` + "\n"),
)
为ptr和值产生相同的结果:
<a href="https-google.com-/path">pointer</a>
<a href="https-google.com-/path">value</a>
游乐场:https://play.golang.org/p/DMTFF3fueau
有趣的是,如果f占用ptr,它就会以同样的方式失败。