func (i zgokFileInfo) Size() int64 {
	return i.size
}
Get size.
Implements [os.FileInfo.Size]
package zgok
import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"
)
const (
	APP   = "zgok"  
	MAJOR = 0       
	MINOR = 0       
	REV   = 1       
)
func Version() string {
	return fmt.Sprintf("%s-%d.%d.%d", APP, MAJOR, MINOR, REV)
}
type FileSystem interface {
	AddFile(file File)
	GetFile(path string) (File, error)
	ReadFile(path string) ([]byte, error)
	ReadFileString(path string) (string, error)
	Paths() []string
	SubFileSystem(rootPath string) (FileSystem, error)
	Signature() Signature
	SetSignature(signature Signature)
	String() string
	Open(name string) (http.File, error)      
	FileServer(basePath string) http.Handler  
}
type zgokFileSystem struct {
	signature Signature        
	rootPath  string           
	fileMap   map[string]File  
}
func NewFileSystem() FileSystem {
	return &zgokFileSystem{
		signature: nil,
		rootPath:  APP,
		fileMap:   make(map[string]File),
	}
}
func RestoreFileSystem(path string) (FileSystem, error) {
	exeBytes, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	sigOffset := len(exeBytes) - SIGNATURE_BYTE_SIZE
	sigBytes := exeBytes[sigOffset:]
	signature, err := RestoreSignature(sigBytes)
	if err != nil {
		return nil, err
	}
	zipOffset := signature.ExeSize()
	zipBytes := exeBytes[zipOffset:sigOffset]
	unzipper := NewUnzipper(&zipBytes)
	zfs, err := unzipper.Unzip()
	if err != nil {
		return nil, err
	}
	zfs.SetSignature(signature)
	return zfs, nil
}
func (zfs *zgokFileSystem) AddFile(file File) {
	key := filepath.ToSlash(file.Path())
	zfs.fileMap[key] = file
}
func (zfs *zgokFileSystem) GetFile(path string) (File, error) {
	key := filepath.ToSlash(filepath.Join(zfs.rootPath, path))
	file, exists := zfs.fileMap[key]
	if !exists {
		return nil, fmt.Errorf("file doesn't exist")
	}
	return file, nil
}
func (zfs *zgokFileSystem) ReadFile(path string) ([]byte, error) {
	file, err := zfs.GetFile(path)
	if err != nil {
		return []byte{}, err
	}
	return file.Bytes(), nil
}
func (zfs *zgokFileSystem) ReadFileString(path string) (string, error) {
	bytes, err := zfs.ReadFile(path)
	if err != nil {
		return "", err
	}
	str := string(bytes)
	return str, nil
}
func (zfs *zgokFileSystem) Paths() []string {
	paths := []string{}
	prefix := zfs.rootPath + "/"
	for key := range zfs.fileMap {
		if strings.HasPrefix(key, prefix) {
			relPath := strings.TrimPrefix(key, prefix)
			paths = append(paths, relPath)
		}
	}
	sort.Strings(paths)
	return paths
}
func (zfs *zgokFileSystem) SubFileSystem(rootPath string) (FileSystem, error) {
	if strings.Contains(rootPath, "..") {
		return nil, fmt.Errorf(`no double dots(..) are allowed in root path`)
	}
	newRootPath := filepath.ToSlash(filepath.Join(zfs.rootPath, rootPath))
	subFs := &zgokFileSystem{
		signature: zfs.signature,
		rootPath:  newRootPath,
		fileMap:   make(map[string]File),
	}
	for key, value := range zfs.fileMap {
		if key[0:len(newRootPath)] == newRootPath {
			subFs.fileMap[key] = value
		}
	}
	return subFs, nil
}
func (zfs *zgokFileSystem) Signature() Signature {
	return zfs.signature
}
func (zfs *zgokFileSystem) SetSignature(signature Signature) {
	zfs.signature = signature
}
func (zfs *zgokFileSystem) String() string {
	return zfs.Signature().String()
}
func (zfs *zgokFileSystem) Open(name string) (http.File, error) {
	path := strings.TrimLeft(name, "/")
	file, err := zfs.GetFile(path)
	if err != nil {
		dir := &zgokFile{
			fileInfo: zgokFileInfo{
				name: filepath.Base(path),
				mode: os.ModeDir | os.ModePerm,
			},
		}
		return dir, nil
	}
	file.SetNewReader()
	return file, nil
}
type File interface {
	SetPath(path string)                           
	Path() string                                  
	SetFileInfo(fileInfo os.FileInfo)              
	FileInfo() os.FileInfo                         
	SetBytes(content []byte)                       
	Bytes() []byte                                 
	SetNewReader()                                 
	Close() error                                  
	Read(p []byte) (int, error)                    
	Readdir(count int) ([]os.FileInfo, error)      
	Seek(offset int64, whence int) (int64, error)  
	Stat() (os.FileInfo, error)                    
}
type zgokFile struct {
	path     string         
	fileInfo os.FileInfo    
	content  []byte         
	reader   *bytes.Reader  
}
func NewZgokFile() File {
	return &zgokFile{}
}
func (zf *zgokFile) SetPath(path string) {
	zf.path = strings.Replace(path, `\`, "/", -1)
}
func (zf *zgokFile) Path() string {
	return zf.path
}
func (zf *zgokFile) SetFileInfo(fileInfo os.FileInfo) {
	zf.fileInfo = fileInfo
}
func (zf *zgokFile) FileInfo() os.FileInfo {
	return zf.fileInfo
}
func (zf *zgokFile) SetBytes(content []byte) {
	zf.content = content
}
func (zf *zgokFile) Bytes() []byte {
	return zf.content
}
func (zf *zgokFile) SetNewReader() {
	reader := bytes.NewReader(zf.content)
	zf.reader = reader
}
func (zf *zgokFile) Close() error {
	return nil
}
func (zf *zgokFile) Read(p []byte) (int, error) {
	return zf.reader.Read(p)
}
func (zf *zgokFile) Readdir(count int) ([]os.FileInfo, error) {
	return nil, fmt.Errorf(`not allowed to "Readdir()"`)
}
func (zf *zgokFile) Seek(offset int64, whence int) (int64, error) {
	return zf.reader.Seek(offset, whence)
}
func (zf *zgokFile) Stat() (os.FileInfo, error) {
	return zf.fileInfo, nil
}
type zgokFileInfo struct {
	name    string       
	size    int64        
	mode    os.FileMode  
	modTime time.Time    
}
func (i zgokFileInfo) Name() string {
	return i.name
}