github.com/hairyhenderson/gomplate/v3@v3.11.7/internal/iohelpers/readers.go (about) 1 package iohelpers 2 3 import ( 4 "io" 5 "sync" 6 ) 7 8 // LazyReadCloser provides an interface to a ReadCloser that will open on the 9 // first access. The wrapped io.ReadCloser must be provided by 'open'. 10 func LazyReadCloser(open func() (io.ReadCloser, error)) io.ReadCloser { 11 return &lazyReadCloser{ 12 opened: sync.Once{}, 13 open: open, 14 } 15 } 16 17 type lazyReadCloser struct { 18 r io.ReadCloser 19 // caches the error that came from open(), if any 20 openErr error 21 open func() (io.ReadCloser, error) 22 opened sync.Once 23 } 24 25 var _ io.ReadCloser = (*lazyReadCloser)(nil) 26 27 func (l *lazyReadCloser) openReader() (r io.ReadCloser, err error) { 28 l.opened.Do(func() { 29 l.r, l.openErr = l.open() 30 }) 31 return l.r, l.openErr 32 } 33 34 func (l *lazyReadCloser) Close() error { 35 r, err := l.openReader() 36 if err != nil { 37 return err 38 } 39 return r.Close() 40 } 41 42 func (l *lazyReadCloser) Read(p []byte) (n int, err error) { 43 r, err := l.openReader() 44 if err != nil { 45 return 0, err 46 } 47 return r.Read(p) 48 }