Hi K,

Thanks for your response.  It looks to me like this would give me both an HTML template and a text template.  In my case, it's an either-or thing, which is what is so frustrating.  If the page is an html page, it stores an html/template in the map.  If it's a csv page, it stores a text/template in the map (although currently this has to be a different map).  I have to have two sets of functions to interact with those maps and their templates, where the primary differences are, for example, whether it calls htmlTemplate.Must() or textTemplate.Must(), or whether the function accepts as an argument a *htmlTemplate.Template or a *textTemplate.Template.

I suppose that I could make my own package to wrap the two packages,  let's call it bothTemplates for the purpose of example:

package bothTemplates

import (
    text "text/template"
    html "html/template"
)

type BothTemplates struct {
    isHTML bool
    t *text.Template
    h *html.Template
}

And then wrap every single one of the functions, or at least the functions that I use (although that's most of the functions, so for completeness' sake I really may as well just go ahead and wrap all of them) to choose whether to use t and text/template or h and html/template based on the value of isHTML, and to allow me to pass that bool to the functions which create a new Template.  At least then all of the redundancy would be decently out of sight, and I would only have to maintain it if the template packages change.

But is that really necessary?  Isn't this the purpose of interfaces -- so that you can take two or more types with identical functions and plug in whichever one you need to use in that case?  Are interfaces really, truly incompatible with chaining?  I think that's what this comes down to -- the text/template and html/template packages are designed for function chaining, so nearly every function returns a pointer to its own type.

Thanks,
Renee Jylkka

On 12/31/2018 8:53 PM, K Davidson wrote:
One way to accomplish this may be to use embedding to wrap both Templates into a new type:

|
packagemain

import(
    txt "text/template"
"html/template"
)

// CsvTemplate wraps a html/template.Template and adds a text/template.Template // field for CSV output.
type CsvTemplatestruct{
template.Template
    t txt.Template
}
|


On Monday, December 31, 2018 at 1:51:34 PM UTC-7, Renee Jylkka wrote:

    Hello,

    The project that I am working on is a web app written on a custom
    web server using Go and Go templates.  I store all of the
    templates in a map[string]Template, where the string is the page
    name.  When someone visits a page, the server checks whether that
    page is in the map, then if so calls a function to fill in a data
    structure, then executes the appropriate template, passing it the
    data structure.  All was rosy until I was asked to create csv
    downloads for some of the more complex pages.  I cannot use a
    html/template.Template for those pages, I have to use a
    text/template.Template for those pages, otherwise the character
    escaping implemented by html/template creates extra columns in
    some of the rows.  My immediate thought was that since
    text/template.Template and html/template.Template have identical
    function lists, I should of course create an interface which would
    be implemented by both types. However, I have no idea how to
    create an interface to include arguments and return types of that
    interface type, such as:
    func Must(t *Template, err error) *Template
    func (t *Template) Funcs(funcMap FuncMap) *Template

    If I try to use *Template, the compiler gives an error that
    Template is undefined.  If I use my interface name in place of
    *Template, the compiler gives the error that neither
    text/template.Template nor html/template.Template implements my
    interface.  Both of these are expected behavior, but of course if
    I use text/template.Template or html/template.Template in place of
    *Template, only one of the two packages would implement my interface.

    Is there a correct way to wrap these two data types (using an
    interface or otherwise) so that I can deal with either one in the
    same data structures and functions, or am I stuck with a lot of
    duplicate code and data structures, with only slight differences
    beyond which package I'm using?

    Thanks!
    Renee Jylkka

--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group. To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/4p3-Q4pUJv8/unsubscribe. To unsubscribe from this group and all its topics, send an email to golang-nuts+unsubscr...@googlegroups.com <mailto:golang-nuts+unsubscr...@googlegroups.com>.
For more options, visit https://groups.google.com/d/optout.

--
Renee Jylkka
Ormandy, Inc.
re...@ormandy.com

Please direct all support requests to supp...@ormandysoftware.com

NOTICE:  This communication, including attachments, is for the exclusive use of 
addressee and may contain proprietary, confidential and/or privileged 
information.  If the reader of this communication is not the intended 
recipient, or an employee or agent responsible for delivering this message to 
the intended recipient, you are hereby notified that any dissemination, 
distribution or copying of this communication or any attachments is strictly 
prohibited. If you are not the intended recipient, please notify the sender 
immediately by return e-mail, delete this communication and destroy all copies.

--
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to