func SearchFile(filename string, paths ...string) (fullPath string, err error) {
	for _, path := range paths {
		if fullPath = filepath.Join(path, filename); IsExist(fullPath) {
			return
		}
	}
	err = fmt.Errorf("%s not found in paths", fullPath)
	return
}
Search a file in paths.
this is often used in search config file in /etc ~/
package file
import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path"
	"path/filepath"
	"strings"
	"time"
)
func SelfPath() string {
	path, _ := filepath.Abs(os.Args[0])
	return path
}
func RealPath(fp string) (string, error) {
	if path.IsAbs(fp) {
		return fp, nil
	}
	wd, err := os.Getwd()
	return path.Join(wd, fp), err
}
func SelfDir() string {
	return filepath.Dir(SelfPath())
}
func Basename(fp string) string {
	return path.Base(fp)
}
func Dir(fp string) string {
	return path.Dir(fp)
}
func InsureDir(fp string) error {
	if IsExist(fp) {
		return nil
	}
	return os.MkdirAll(fp, os.ModePerm)
}
func EnsureDir(fp string) error {
	return os.MkdirAll(fp, os.ModePerm)
}
func EnsureDirRW(dataDir string) error {
	err := EnsureDir(dataDir)
	if err != nil {
		return err
	}
	checkFile := fmt.Sprintf("%s/rw.%d", dataDir, time.Now().UnixNano())
	fd, err := Create(checkFile)
	if err != nil {
		if os.IsPermission(err) {
			return fmt.Errorf("open %s: rw permission denied", dataDir)
		}
		return err
	}
	Close(fd)
	Remove(checkFile)
	return nil
}
func Create(name string) (*os.File, error) {
	return os.Create(name)
}
func Remove(name string) error {
	return os.Remove(name)
}
func Close(fd *os.File) error {
	return fd.Close()
}
func Ext(fp string) string {
	return path.Ext(fp)
}
func Rename(src string, target string) error {
	return os.Rename(src, target)
}
func Unlink(fp string) error {
	return os.Remove(fp)
}
func IsFile(fp string) bool {
	f, e := os.Stat(fp)
	if e != nil {
		return false
	}
	return !f.IsDir()
}
func IsExist(fp string) bool {
	_, err := os.Stat(fp)
	return err == nil || os.IsExist(err)
}