Skip to content

Latest commit

 

History

History
66 lines (58 loc) · 1.56 KB

获取程序所在目录.md

File metadata and controls

66 lines (58 loc) · 1.56 KB
import (
	"fmt"
	"log"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strings"
)

func main() {
	fmt.Println("GetCurrentAbsPath = ", GetCurrentAbsPath())
}

//
// `go run` 命令会将源代码编译到系统TEMP或TMP环境变量目录中然后动执行.
// 而 `go build` 只会在当前目录编译出可执行文件, 并不会自动执行.
//
// 所以在获取程序路径时要先判断当前程序是否在 TEMP/TMP 目录下:
//
// - 如果在, 说明当前程序是使用 `go run` 命令启动. 想要获取真实的路径就需要
// 使用 runtime.Caller 来获取.
//
// - 如果不在, 说明当前程序是用 `go build` 命令构建编译成可执行程序. 我们直
// 接使用 os.Executable 获取可执行程序所在目录即可.
//
func GetCurrentAbsPath() string {

	dir := getCurrentAbsPathByExecutable()

	tmpDir, _ := filepath.EvalSymlinks(os.TempDir())

	if strings.Contains(dir, tmpDir) {
		return getCurrentAbsPathByCaller()
	}
	return dir
}

//
// 获取当前执行文件绝对路径(`go build`)
//
// 如果是通过 `go build` 启动, 需要使用 os.Executable 获取可执行程序所在目录.
//
func getCurrentAbsPathByExecutable() string {
	dir, err := os.Executable()
	if err != nil {
		log.Fatal(err)
	}

	dir, _ = filepath.EvalSymlinks(filepath.Dir(dir))
	return dir
}

//
// 获取当前执行文件绝对路径(`go run`)
//
// 如果是通过 `go run` 启动, 需要使用 runtime.Caller 获取程序路径.
//
func getCurrentAbsPathByCaller() string {
	if _, filename, _, ok := runtime.Caller(0); ok {
		return path.Dir(filename)
	}
	return ""
}