我正在尝试测试模板生成工具。为了做到这一点,我认为捕获模板执行输出的最简单方法是使用io writer并在测试期间提供它。问题在于,由于某些原因,接收器未被更新"使用模板输出。希望下面的代码更好地解释了我面临的问题。
package main
import "fmt"
import "text/template"
type Company struct{
Name string
}
type Companies []Company
func main() {
s := new(stringer)
v := Companies{Company{Name:"Sony"}}
tmp := template.Must(template.New("main").Parse(src))
if err := tmp.Execute(s, v); err !=nil{
panic(err)
}
if *s != "this is the header template"{
fmt.Println("expected: \"this is the header template\" received: ", *s)
}else{
fmt.Println("s is %v", *s)
}
}
type stringer string
func (s *stringer)Write(b []byte)(int, error){
*s = stringer(b)
return len(b), nil
}
var src = `
this is the header template
{{range .}}
{{.Name}}
{{end}}
`
答案 0 :(得分:2)
您的stringer
类型只是*string
类型的“别名”。 Go中的string
是不可变的。您不应该使用string
或指向string
的指针来构建模板的输出,因为您无法修改string
,您只能创建一个新的(扔掉旧的。)
template.Execute()
需要io.Writer
。可能会多次调用输出的Write()
方法,并且您的stringer.Write()
方法始终会丢弃先前写入的数据。您可以通过始终将新数据连接到旧数据来解决此问题:
*s = *s + stringer(b)
但是这个解决方案非常低效(它会生成新的string
并抛弃旧的)。
更好且易于使用的替代方案是bytes.Buffer
。您可以创建一个实现Writer
接口的字节缓冲区,如下所示:
bytes.NewBuffer(nil)
您无需创建自己的stringer
类型。在Go Playground上尝试修改后的程序。