package tplx import ( `bytes` htmlTpl `html/template` txtTpl `text/template` ) // MustTplStrToStr wraps [TplStrToStr] but will panic on a non-nil error instead of returning it. func MustTplStrToStr(tplStr string, typ tplType, obj any) (s string) { var err error if s, err = TplStrToStr(tplStr, typ, obj); err != nil { panic(err) } return } // MustTplToStr wraps [TplToStr] but will panic on error instead of returning it. func MustTplToStr[T Template](tpl T, obj any) (s string) { var err error if s, err = TplToStr(tpl, obj); err != nil { panic(err) } return } // MustTplToStrWith wraps [TplToStrWith] but will panic on error instead of returning it. func MustTplToStrWith[T Template](tpl T, tplNm string, obj any) (s string) { var err error if s, err = TplToStrWith(tpl, tplNm, obj); err != nil { panic(err) } return } /* TplStrToStr takes in a template string, a template type (see i.e. [TplTypeText], [TplTypeHtml]), and an object and renders to a string. This is obviously quite inflexible - there's no way to provide a [text/template.FuncMap]/[html/template.FuncMap], for instance, but if more advanced template features aren't needed then this might just do the trick. If you need something more flexible, see [TplToStr] instead. */ func TplStrToStr(tplStr string, typ tplType, obj any) (out string, err error) { var ttpl *txtTpl.Template var htpl *htmlTpl.Template var buf *bytes.Buffer = new(bytes.Buffer) switch typ { case TplTypeText: if ttpl, err = txtTpl.New("").Parse(tplStr); err != nil { return } if err = ttpl.Execute(buf, obj); err != nil { return } case TplTypeHtml: if htpl, err = htmlTpl.New("").Parse(tplStr); err != nil { return } if err = htpl.Execute(buf, obj); err != nil { return } default: err = ErrInvalidTplType return } out = buf.String() return } /* TplToStr takes in an [html/template] or [text/template] and an object and executes it. PLEASE NOTE that it is expected that `tpl` has already had at least one template string `.Parse()`'d in. If you haven't used generics in Golang yet, this function would be used via something like the following complete example for both a [text/template.Template] (import-aliased as `txtT.Template`) and an [html/template.Template] (import-aliased as `htmlT.Template`). import ( "fmt" "log" txtT "text/template" htmlT "html/template" `r00t2.io/goutils/tplx` ) type ( S struct { Name string } ) var ( tTpl *txtT.Template hTpl *htmlT.Template ) const tTplStr string = "Greetings, {{ .Name }}!\n" const hTplStr string = `
Hello, {{ .Name }}. Good to see you.
` func main() { var err error var s string var o *S o = &S{ Name: "Bob", } // A text template. if tTpl, err = txtT. New("my_txt_template"). Parse(tTplStr); err != nil { log.Panicf("Failed to parse text template string '%s': %v\n", tTplStr, err) } if s, err = tplx.TplToStr[*txtT.Template](tTpl, o); err != nil { log.Panicf("Failed to render text template to string: %v\n", err) } fmt.Println(s) // An HTML template. if hTpl, err = htmlT. New("index.html"). Parse(hTplStr); err != nil { log.Panicf("Failed to parse HTML template string '%s': %v\n", hTplStr, err) } if s, err = tplx.TplToStr[*htmlT.Template](hTpl, o); err != nil { log.Panicf("Failed to render HTML template to string: %v\n", err) } fmt.Println(s) } Additionally, because this function uses a union type [Template], you can even leave the type indicator off. For example: // ... if s, err = tplx.TplToStr(tTpl, o); err != nil { log.Panicf("Failed to render text template to string: %v\n", err) } // ... if s, err = tplx.TplToStr(hTpl, o); err != nil { log.Panicf("Failed to render HTML template to string: %v\n", err) } // ... However, this is not recommended for readability purposes - including the type indicator indicates (heh heh) to others reading your code what type `tTpl` and `hTpl` are without needing to cross-reference their declaration/assignment/definition. For more information on generics in Golang, see: * The introductory [blog post] * The official [tutorial] * The syntax [reference doc] * The (community-maintained/unofficial) [Go by Example: Generics] [blog post]: https://go.dev/blog/intro-generics [tutorial]: https://go.dev/doc/tutorial/generics [reference doc]: https://go.dev/ref/spec#Instantiations [Go by Example: Generics]: https://gobyexample.com/generics */ func TplToStr[T Template](tpl T, obj any) (out string, err error) { var buf *bytes.Buffer = new(bytes.Buffer) if err = tpl.Execute(buf, obj); err != nil { return } out = buf.String() return } /* TplToStrWith functions the exact same as [TplToStr] but allows you to specify the template entry point (template name) named `nm`. For example (see [TplToStr] for a full example): // ... var tplNm string = "index.html" if s, err = tplx.TplToStrWith(tTpl, tplNm, o); err != nil { log.Panicf("Failed to render HTML template '%s' to string: %v\n", tplNm, err) } // ... would call the equivalent of: // ... if err = tpl.ExecuteTemplate(