为了账号安全,请及时绑定邮箱和手机立即绑定

为什么 IO.Writer 没有填充接收器?

为什么 IO.Writer 没有填充接收器?

Go
阿晨1998 2021-09-13 15:28:36
我正在尝试测试模板生成工具。为了做到这一点,我认为捕获模板执行输出的最简单方法是使用 io writer 并在测试期间提供它。问题是由于某些原因,接收器没有用模板输出“更新”。希望下面的代码更好地解释了我面临的问题。package mainimport "fmt"import "text/template"type Company struct{    Name string} type Companies []Companyfunc 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 stringfunc (s *stringer)Write(b []byte)(int, error){    *s = stringer(b)    return len(b), nil}var src = ` this is the header template    {{range .}}    {{.Name}}    {{end}}`http://play.golang.org/p/y4zWgyd5G1
查看完整描述

1 回答

?
桃花长相依

TA贡献1860条经验 获得超8个赞

您的stringer类型只是输入的“别名” *stringstring在 Go 中是不可变的。您不应该使用 astring或指向 a 的指针来string构建模板的输出,因为您不能修改 a string,您只能创建一个新的(并丢弃旧的)。

template.Execute()期待一个io.WriterWrite()输出的方法可能会被多次调用,并且您的stringer.Write()方法总是会丢弃之前写入它的数据。您可以通过始终将新数据连接到旧数据来修复它,如下所示:

*s = *s + stringer(b)

但是这个解决方案非常低效(它生成新string的并丢弃旧的)。

一个更好且随时可用的替代方案是bytes.Buffer. 您可以创建一个字节缓冲区来实现这样的Writer接口:

bytes.NewBuffer(nil)

您不需要创建自己的stringer类型。在Go Playground上试试你修改过的程序。


查看完整回答
反对 回复 2021-09-13
  • 1 回答
  • 0 关注
  • 161 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信