項目交叉編譯爲可執行文件以後,在其餘目錄執行文件時提示找不到配置文件shell
2020/03/14 20:44:23 配置文件讀取失敗 open config.ini: no such file or directory
直接採用如下代碼獲取到實際執行文件的路徑,而後拼接配置文件便可bash
file, _ := exec.LookPath(os.Args[0]) path, _ := filepath.Abs(file) index := strings.LastIndex(path, string(os.PathSeparator)) path = path[:index]
os.Args是用來獲取命令行執行參數分片的,當使用go run
時ui
$ go run main.go [/var/folders/3s/5v6r481x17x5ks_7q1dzmlsw0000gp/T/go-build231739964/b001/exe/main]
分片0會是一串複雜的路徑,緣由是直接run go文件時會將文件轉移到臨時路徑下,而後再進行編譯和執行,若是直接執行編譯後的文件就不同了,此時分片0爲執行文件的相對路徑命令行
$ go build $ ./jira_reminder [./jira-reminder]
接下來看一下LookPath方法的做用,官方文檔中是這樣解釋的code
// LookPath searches for an executable named file in the // directories named by the PATH environment variable. // If file contains a slash, it is tried directly and the PATH is not consulted. // The result may be an absolute path or a path relative to the current directory.
大體意思就是它會去環境變量中找這個可執行文件的絕對路徑,或相對於當前目錄的路徑。接下來執行了filepath.Abs
方法遞歸
// Abs returns an absolute representation of path. // If the path is not absolute it will be joined with the current // working directory to turn it into an absolute path. The absolute // path name for a given file is not guaranteed to be unique. // Abs calls Clean on the result.
意思是它會根據傳入的路徑計算出絕對路徑,若是傳入的爲相對路徑,那麼它會把當前路徑拼接上element
此時返回的path是一個包含可執行文件在內的完整路徑,咱們只須要精確到目錄便可rem
index := strings.LastIndex(path, string(os.PathSeparator))
以上代碼會搜索最後一個目錄分隔符的位置(下標),而後經過如下代碼將路徑中下標後面的字符串切割掉文檔
path = path[:index]
這樣就完成了目錄的獲取,接下來再拼接上咱們實際的配置文件就能夠了字符串
發現不調用exec.LookPath也是能夠達到查詢絕對路徑的目的的,那麼exec.LookPath還有什麼用?
path, _ := filepath.Abs(os.Args[0]) index := strings.LastIndex(path, string(os.PathSeparator)) path = path[:index]
咱們來看一下源碼,exec.LookPath的做用是從相對路徑或環境變量PATH中遞歸找可執行文件,這起着一個校驗的做用,檢測調用的可執行文件是否是真的存在,若是存在再繼續往下拼接出絕對路徑,由於咱們的執行文件的確是存在的,因此就算不使用exec.LookPath也能夠達到目的
func LookPath(file string) (string, error) { // NOTE(rsc): I wish we could use the Plan 9 behavior here // (only bypass the path if file begins with / or ./ or ../) // but that would not match all the Unix shells. if strings.Contains(file, "/") { err := findExecutable(file) if err == nil { return file, nil } return "", &Error{file, err} } path := os.Getenv("PATH") for _, dir := range filepath.SplitList(path) { if dir == "" { // Unix shell semantics: path element "" means "." dir = "." } path := filepath.Join(dir, file) if err := findExecutable(path); err == nil { return path, nil } } return "", &Error{file, ErrNotFound} }