func Unzip(src, dest string) error {
	r, err := zip.OpenReader(src)
	if err != nil {
		return err
	}
	defer func() {
		if err := r.Close(); err != nil {
			panic(err)
		}
	}()
	MkdirAll(dest, 0755)
	extractAndWriteFile := func(f *zip.File) error {
		rc, err := f.Open()
		if err != nil {
			return err
		}
		defer func() {
			if err := rc.Close(); err != nil {
				panic(err)
			}
		}()
		thePath := Join(dest, f.Name)
		if f.FileInfo().IsDir() {
			MkdirAll(thePath, f.Mode())
		} else {
			MkdirAll(filepath.Dir(thePath), f.Mode())
			f, err := OpenFile(thePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
			if err != nil {
				return err
			}
			defer func() {
				if err := f.Close(); err != nil {
					panic(err)
				}
			}()
			_, err = io.Copy(f, rc)
			if err != nil {
				return err
			}
		}
		return nil
	}
	for _, f := range r.File {
		err := extractAndWriteFile(f)
		if err != nil {
			return err
		}
	}
	return nil
}
Unzip a file in a destination path
https://stackoverflow.com/questions/20357223/easy-way-to-unzip-file-with-golang
package fs
import (
	"archive/zip"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"regexp"
	"strings"
)
type File interface {
	io.Reader
	io.Writer
	io.Closer
	Fd() uintptr
	Readdirnames(n int) ([]string, error)
	Readdir(int) ([]os.FileInfo, error)
	Seek(int64, int) (int64, error)
	Stat() (os.FileInfo, error)
}
func fixpath(name string) string {
	abspath, err := filepath.Abs(name)
	if err == nil {
		return UncPath(abspath)
	}
	return name
}
func UncPath(s string) string {
	isAbsWinDrive := regexp.MustCompile(`^[a-zA-Z]\:\\`)
	s = strings.Replace(s, `/`, `\`, -1)
	if strings.HasPrefix(s, `\\`) {
		if strings.HasPrefix(s, `\\?\`) {
			return s
		}
		return `\\?\UNC\` + strings.TrimPrefix(s, `\\`)
	}
	if isAbsWinDrive.MatchString(s) {
		return `\\?\` + s
	}
	return s
}
func RemoveUnc(s string) string {
	return strings.TrimLeft(s, `\\?\`)
}
func Open(name string) (File, error) {
	return os.OpenFile(fixpath(name), os.O_RDONLY, 0)
}
func ClearCache(f File) error {
	return nil
}
func Chmod(name string, mode os.FileMode) error {
	return os.Chmod(fixpath(name), mode)
}
func Mkdir(name string, perm os.FileMode) error {
	return os.Mkdir(fixpath(name), perm)
}
func MkdirAll(path string, perm os.FileMode) error {
	return os.MkdirAll(fixpath(path), perm)
}
func Readlink(name string) (string, error) {
	return os.Readlink(fixpath(name))
}
func Remove(name string) error {
	return os.Remove(fixpath(name))
}
func RemoveAll(path string) error {
	return os.RemoveAll(fixpath(path))
}
func Rename(oldpath, newpath string) error {
	return os.Rename(fixpath(oldpath), fixpath(newpath))
}
func Symlink(oldname, newname string) error {
	return os.Symlink(fixpath(oldname), fixpath(newname))
}
func Stat(name string) (os.FileInfo, error) {
	return os.Stat(fixpath(name))
}
func Lstat(name string) (os.FileInfo, error) {
	return os.Lstat(fixpath(name))
}
func Create(name string) (*os.File, error) {
	return os.Create(fixpath(name))
}
func OpenFile(name string, flag int, perm os.FileMode) (*os.File, error) {
	return os.OpenFile(fixpath(name), flag, perm)
}
func Walk(root string, walkFn filepath.WalkFunc) error {
	return filepath.Walk(fixpath(root), walkFn)
}
func Join(elem ...string) string {
	for i, e := range elem {
		if e != "" {
			return fixpath(path.Clean(strings.Join(elem[i:], "/")))
		}
	}
	return ""
}
func CopyFile(src, dst string) (err error) {
	in, err := Open(src)
	if err != nil {
		return
	}
	defer in.Close()
	out, err := Create(dst)
	if err != nil {
		return
	}
	defer func() {
		if e := out.Close(); e != nil {
			err = e
		}
	}()
	_, err = io.Copy(out, in)
	if err != nil {
		return
	}
	err = out.Sync()
	if err != nil {
		return
	}
	si, err := Stat(src)
	if err != nil {
		return
	}
	err = Chmod(dst, si.Mode())
	if err != nil {
		return
	}
	return
}
func CopyDir(src string, dst string) (err error) {
	src = filepath.Clean(src)
	dst = filepath.Clean(dst)
	si, err := Stat(src)
	if err != nil {
		return err
	}
	if !si.IsDir() {
		return fmt.Errorf("source is not a directory")
	}
	_, err = Stat(dst)
	if err != nil && !os.IsNotExist(err) {
		return
	}
	err = MkdirAll(dst, si.Mode())
	if err != nil {
		return
	}
	entries, err := ioutil.ReadDir(src)
	if err != nil {
		return
	}
	for _, entry := range entries {
		srcPath := Join(src, entry.Name())
		dstPath := Join(dst, entry.Name())
		if entry.IsDir() {
			err = CopyDir(srcPath, dstPath)
			if err != nil {
				return
			}
		} else {
			err = CopyFile(srcPath, dstPath)
			if err != nil {
				return
			}
		}
	}
	return
}
func CreateSubfolder(path string) error {
	if _, err := Stat(path); os.IsNotExist(err) {
		err = MkdirAll(path, 777)
		if err != nil {
			return err
		}
	}
	return nil
}
func FormatWinPath(path string) string {
	return strings.Replace(path, "/", "\\", -1)
}