func RemoveAll(fs VFS, path string) error {
	stat, err := fs.Lstat(path)
	if err != nil {
		if err == os.ErrNotExist {
			return nil
		}
		return err
	}
	if stat.IsDir() {
		files, err := fs.ReadDir(path)
		if err != nil {
			return err
		}
		for _, v := range files {
			filePath := pathpkg.Join(path, v.Name())
			if err := RemoveAll(fs, filePath); err != nil {
				return err
			}
		}
	}
	return fs.Remove(path)
}
RemoveAll removes all files from the given fs and path, including
directories (by removing its contents first).
package vfs
import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	pathpkg "path"
	"strings"
)
var (
	SkipDir = errors.New("skip this directory")
	ErrReadOnly = errors.New("can't write to read only file")
	ErrWriteOnly = errors.New("can't read from write only file")
)
type WalkFunc func(fs VFS, path string, info os.FileInfo, err error) error
func walk(fs VFS, p string, info os.FileInfo, fn WalkFunc) error {
	err := fn(fs, p, info, nil)
	if err != nil {
		if info.IsDir() && err == SkipDir {
			err = nil
		}
		return err
	}
	if !info.IsDir() {
		return nil
	}
	infos, err := fs.ReadDir(p)
	if err != nil {
		return fn(fs, p, info, err)
	}
	for _, v := range infos {
		name := pathpkg.Join(p, v.Name())
		fileInfo, err := fs.Lstat(name)
		if err != nil {
			if err := fn(fs, name, fileInfo, err); err != nil && err != SkipDir {
				return err
			}
			continue
		}
		if err := walk(fs, name, fileInfo, fn); err != nil && (!fileInfo.IsDir() || err != SkipDir) {
			return err
		}
	}
	return nil
}
func Walk(fs VFS, root string, fn WalkFunc) error {
	info, err := fs.Lstat(root)
	if err != nil {
		return fn(fs, root, nil, err)
	}
	return walk(fs, root, info, fn)
}
func makeDir(fs VFS, path string, perm os.FileMode) error {
	stat, err := fs.Lstat(path)
	if err == nil {
		if !stat.IsDir() {
			return fmt.Errorf("%s exists and is not a directory", path)
		}
	} else {
		if err := fs.Mkdir(path, perm); err != nil {
			return err
		}
	}
	return nil
}
func MkdirAll(fs VFS, path string, perm os.FileMode) error {
	cur := "/"
	if err := makeDir(fs, cur, perm); err != nil {
		return err
	}
	parts := strings.Split(path, "/")
	for _, v := range parts {
		cur += v
		if err := makeDir(fs, cur, perm); err != nil {
			return err
		}
		cur += "/"
	}
	return nil
}