Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

text/template: The ability to output an io.Reader #25160

Closed
smasher164 opened this issue Apr 29, 2018 · 5 comments
Closed

text/template: The ability to output an io.Reader #25160

smasher164 opened this issue Apr 29, 2018 · 5 comments

Comments

@smasher164
Copy link
Member

@smasher164 smasher164 commented Apr 29, 2018

Having the ability to templatize and concatenate multiple streams through a template would be highly useful. One can think of this as a generalization of the functionality provided by MultiReader, TeeReader, etc, except we'd have the ability to store stubs in files, and have more granular control of intermediate text and formatting.
For example, I'd like to be able to write something similar to the following:

r := // some predefined io.Reader...
t, _ := template.New("").Parse(`
<html>
    <head>
        <meta charset="UTF-8"><meta name="viewport" content="width=device-width, maximum-scale=1.0">
        <link href="/static/blog.css" rel="stylesheet">
    </head>
    <body>
        {{ . }}
    </body>
</html>
`)
t.Execute(os.Stdout, r)

Currently, I have a workaround using channels, however the overhead of channel communication doesn't make it worth using.

copyReader := func(c chan<- string, r io.Reader) {
	p := make([]byte, 100)
	for {
		n, err := r.Read(p)
		c <- string(p[:n])
		if err != nil {
			close(c)
			break
		}
	}
}
r := // some predefined io.Reader...
t, _ := template.New("").Parse(`
<html>
    <head>
        <meta charset="UTF-8"><meta name="viewport" content="width=device-width, maximum-scale=1.0">
        <link href="/static/blog.css" rel="stylesheet">
    </head>
    <body>
        {{range .}}{{.}}{{end}}
    </body>
</html>
`)
c := make(chan string)
go copyReader(c, r)
t.Execute(os.Stdout, c)
@mvdan
Copy link
Member

@mvdan mvdan commented Apr 29, 2018

Why not use a func in the template like ioutil.ReadAll?

@smasher164
Copy link
Member Author

@smasher164 smasher164 commented Apr 29, 2018

ioutil.ReadAll would require me to buffer all of the stream before outputting it. I'm looking for the ability to output parts of the stream, one after the other, like io.Copy.

@smasher164
Copy link
Member Author

@smasher164 smasher164 commented Apr 29, 2018

The ioutil.ReadAll solution is probably fine for most users, so it's okay to close this issue. That being said, having a more traditional looping construct would open up the template package to more stream-like use-cases. Right now, the range directive is restricted to iterable types.

@andybons
Copy link
Member

@andybons andybons commented Apr 30, 2018

having a more traditional looping construct would open up the template package to more stream-like use-cases. Right now, the range directive is restricted to iterable types.

Please feel free to open a proposal for your feature question per https://golang.org/s/proposal

@andybons andybons closed this Apr 30, 2018
@gopherbot
Copy link

@gopherbot gopherbot commented Dec 9, 2018

Change https://golang.org/cl/153339 mentions this issue: text/template: make Execute copy io.Reader content

@golang golang locked and limited conversation to collaborators Dec 9, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
4 participants
You can’t perform that action at this time.