func findAndWriteFiles(buf *bytes.Buffer, fs http.FileSystem, toc *toc) error {
	walkFn := func(path string, fi os.FileInfo, r io.ReadSeeker, err error) error {
		if err != nil {
			return err
		}
		switch fi.IsDir() {
		case false:
			file := &fileInfo{
				Path:             path,
				Name:             pathpkg.Base(path),
				ModTime:          fi.ModTime().UTC(),
				UncompressedSize: fi.Size(),
			}
			marker := buf.Len()
			err = writeCompressedFileInfo(buf, file, r)
			switch err {
			default:
				return err
			case nil:
				toc.HasCompressedFile = true
			case errCompressedNotSmaller:
				_, err = r.Seek(0, io.SeekStart)
				if err != nil {
					return err
				}
				buf.Truncate(marker)
				err = writeFileInfo(buf, file, r)
				if err != nil {
					return err
				}
				toc.HasFile = true
			}
		case true:
			entries, err := readDirPaths(fs, path)
			if err != nil {
				return err
			}
			dir := &dirInfo{
				Path:    path,
				Name:    pathpkg.Base(path),
				ModTime: fi.ModTime().UTC(),
				Entries: entries,
			}
			toc.dirs = append(toc.dirs, dir)
			err = t.ExecuteTemplate(buf, "DirInfo", dir)
			if err != nil {
				return err
			}
		}
		return nil
	}
	err := vfsutil.WalkFiles(fs, "/", walkFn)
	return err
}
findAndWriteFiles recursively finds all the file paths in the given directory tree.
They are added to the given map as keys. Values will be safe function names
for each file, which will be used when generating the output code.
package vfsgen
import (
	"bytes"
	"compress/gzip"
	"errors"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	pathpkg "path"
	"sort"
	"strconv"
	"text/template"
	"time"
	"github.com/shurcooL/httpfs/vfsutil"
)
func Generate(input http.FileSystem, opt Options) error {
	opt.fillMissing()
	buf := new(bytes.Buffer)
	err := t.ExecuteTemplate(buf, "Header", opt)
	if err != nil {
		return err
	}
	var toc toc
	err = findAndWriteFiles(buf, input, &toc)
	if err != nil {
		return err
	}
	err = t.ExecuteTemplate(buf, "DirEntries", toc.dirs)
	if err != nil {
		return err
	}
	err = t.ExecuteTemplate(buf, "Trailer", toc)
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(opt.Filename, buf.Bytes(), 0644)
	return err
}
type toc struct {
	dirs []*dirInfo
	HasCompressedFile bool  
	HasFile           bool  
}
type fileInfo struct {
	Path             string
	Name             string
	ModTime          time.Time
	UncompressedSize int64
}
type dirInfo struct {
	Path    string
	Name    string
	ModTime time.Time
	Entries []string
}