func RealPathWalk(root string, walkFn filepath.WalkFunc) error {
	info, err := os.Lstat(root)
	if err != nil {
		return walkFn(root, nil, err)
	}
	visited := make(map[string]bool)
	return realPathWalk(root, info, walkFn, visited)
}
RealPathWalk is like filepath.Walk but follows symlinks.
package main
import (
	"errors"
	"io"
	"os"
	"path/filepath"
	"sort"
	"strconv"
	"sync"
	"time"
	"github.com/yookoala/realpath"
)
func Basename(path string) string {
	if path == "" {
		return ""
	}
	path = path[len(filepath.VolumeName(path)):]
	i := len(path) - 1
	for i >= 0 && !os.IsPathSeparator(path[i]) {
		i--
	}
	if i >= 0 {
		path = path[i+1:]
	}
	return path
}
func CopyFile(dst, src string) error {
	sf, err := os.Open(src)
	if err != nil {
		return err
	}
	defer sf.Close()
	sstat, err := sf.Stat()
	if err != nil {
		return err
	}
	if !sstat.Mode().IsRegular() {
		return errors.New("not regular file")
	}
	df, err := os.OpenFile(dst, os.O_WRONLY|os.O_TRUNC, sstat.Mode())
	if err != nil {
		return err
	}
	defer df.Close()
	_, err = io.Copy(df, sf)
	return err
}
func readDirNames(dirname string) ([]string, error) {
	f, err := os.Open(dirname)
	if err != nil {
		return nil, err
	}
	names, err := f.Readdirnames(-1)
	f.Close()
	if err != nil {
		return nil, err
	}
	sort.Strings(names)
	return names, nil
}
func realPathWalk(path string, info os.FileInfo, walkFn filepath.WalkFunc, visited map[string]bool) error {
	realPath, err := realpath.Realpath(path)
	if err == nil {
		path = realPath
		if visited[path] {
			return nil
		}
		visited[path] = true
		var realInfo os.FileInfo
		realInfo, err = os.Lstat(path)
		if err == nil {
			info = realInfo
		}
	}
	err = walkFn(path, info, err)
	if err != nil {
		if info.IsDir() && err == filepath.SkipDir {
			return nil
		}
		return err
	}
	if !info.IsDir() {
		return nil
	}
	names, err := readDirNames(path)
	if err != nil {
		return walkFn(path, info, err)
	}
	for _, name := range names {
		filename := filepath.Join(path, name)
		fileInfo, err := os.Lstat(filename)
		if err != nil {
			if err := walkFn(filename, fileInfo, err); err != nil && err != filepath.SkipDir {
				return err
			}
		} else {
			err = realPathWalk(filename, fileInfo, walkFn, visited)
			if err != nil {
				if !fileInfo.IsDir() || err != filepath.SkipDir {
					return err
				}
			}
		}
	}
	return nil
}