我在net/mail.Address
周围有一个包装器,提供了一些编组逻辑。我正在尝试在模板中使用它,但是我不断得到can't evaluate field String in type EmailAddress
。模板文档说:
数据的尼拉德方法的名称,后跟一个句点, 例如
。方法
结果是调用以dot作为方法的值 接收者dot.Method()。
和
方法调用可以链接在一起,并与字段和键组合 到任何深度:
.Field1.Key1.Method1.Field2.Key2.Method2
因此我谨记这一点:
package main
import (
"bytes"
"fmt"
"html/template"
"net/mail"
"os"
)
type EmailAddress struct{ mail.Address }
type emailFormatter struct {
From EmailAddress
To EmailAddress
}
var tmpl = template.Must(template.New("Sample Text").Parse("From: {{.From.String}}\r" + `
To: {{.To.String}}` + "\r" + `
Content-Type: text/html` + "\r" + `
Subject: Sample Text` + "\r\n\r" + `
<!DOCTYPE html>
<html lang="en">
<head>
<title>Sample Text</title>
<meta charset="utf-8"/>
</head>
<body>
Sample Text
</body>
</html>
`));
func main() {
to := EmailAddress{
mail.Address{
Address: "em@i.l",
Name: "",
},
}
from := EmailAddress{
mail.Address{
Address: "no-reply@test.quest",
Name: "",
},
}
fmt.Println(to.String()) //outputs (as expected) "<em@i.l>"
fmt.Println(from.String()) //outputs (as expected) "<no-reply@test.quest>"
f := emailFormatter{
To: to,
From: from,
}
var buff bytes.Buffer
if err := tmpl.Execute(&buff, f); err != nil {
fmt.Printf("Error: %v\n", err)
os.Exit(1)
}
fmt.Println(buff.String())
}
我已经单独验证了调用EmailAddress.String
是完全合法的,所以我不知道为什么唯一的输出是:
Error: template: Sample Text:1:13: executing "Sample Text" at <.From.String>: can't evaluate field String in type main.EmailAddress
在评论者的建议下,我将通话从.From.String
和.To.String
更改为.From.Address.String
和.To.Address.String
,因为
“
上定义的String
未在EmailAddress
上定义,而是在EmailAddress.Address
”
但结果相同:
Error: template: Sample Text:1:13: executing "Sample Text" at <.From.Address.String>: can't evaluate field String in type mail.Address
答案 0 :(得分:2)
由于String
是使用指针接收器定义的,因此您需要将mail.Address
的“可寻址”实例传递到模板以能够执行该方法。
您可以通过传递指向f
的指针来做到这一点。
if err := tmpl.Execute(&buff, &f); err != nil {
panic(err)
}
或者您也可以通过传递指向EmailAddress
的指针来实现。
type emailFormatter struct {
From *EmailAddress
To *EmailAddress
}
// ...
f := emailFormatter{
To: &to,
From: &from,
}
// ...
if err := tmpl.Execute(&buff, f); err != nil {
panic(err)
}
或者通过传递指向mail.Address
的指针。
type EmailAddress struct{ *mail.Address }
// ...
to := EmailAddress{
&mail.Address{
Address: "em@i.l",
Name: "",
},
}
from := EmailAddress{
&mail.Address{
Address: "no-reply@test.quest",
Name: "",
},
}
f := emailFormatter{
To: to,
From: from,
}
// ...
if err := tmpl.Execute(&buff, f); err != nil {
panic(err)
}
请注意,您不需要在Go代码中执行此操作的原因是因为编译器在那里为您完成了操作。
例如:
fmt.Println(to.String())
成为:
fmt.Println((&to).String())
如果x的方法集(的类型)有效,则x.m()方法调用有效 包含m并且参数列表可以分配给参数列表 的米如果x是可寻址的并且&x的方法集包含m,则x.m()为 (&x).m()
的简写