code: func packDir(srcPath string, recPath string, zw *zip.Writer, fn cae.HookFunc) error {
  	dir, err := os.Open(srcPath)
  	if err != nil {
  		return err
  	}
  	defer dir.Close()
  
  	fis, err := dir.Readdir(0)
  	if err != nil {
  		return err
  	}
  	for _, fi := range fis {
  		if cae.IsFilter(fi.Name()) {
  			continue
  		}
  		curPath := srcPath + "/" + fi.Name()
  		tmpRecPath := filepath.Join(recPath, fi.Name())
  		if err = fn(curPath, fi); err != nil {
  			continue
  		}
  
  		if fi.IsDir() {
  			if err = packFile(srcPath, tmpRecPath, zw, fi); err != nil {
  				return err
  			}
  			err = packDir(curPath, tmpRecPath, zw, fn)
  		} else {
  			err = packFile(curPath, tmpRecPath, zw, fi)
  		}
  		if err != nil {
  			return err
  		}
  	}
  	return nil
  }
docs: // packDir packs a directory and its subdirectories and files
  // recursively to zip.Writer.