Golang でカレントディレクトリ、実行ファイルのパスを取得する (os.Getwd, os.Executable)

カレントディレクトリのパス (os.Getwd)

Golang でカレントディレクトリのパスを取得するには、os.Getwd 関数 を使用します。 戻り値は、カレントディレクトリを示す 絶対パス(フルパス) の文字列になります。 カレントディレクトリは、go run コマンドなどを実行したときのディレクトリのことであり、.go ファイルのあるパスではないことに注意してください。

main.go
package main

import (
	"fmt"
	"os"
)

func main() {
	dir, err := os.Getwd()
	if err != nil {
		panic(err)
	}
	fmt.Println(dir)
}
実行結果
$ cd /Users/maku/hello
$ go run main.go
/Users/maku/hello

$ cd /Users/maku
$ go run hello/main.go
/Users/maku

実行中のファイルのパス (os.Executable)

実行中のファイル (executable) のフルパスを取得するには、os.Executable 関数 を使用します。

main.go
package main

import (
	"fmt"
	"os"
)

func main() {
	path, err := os.Executable()
	if err != nil {
		panic(err)
	}
	fmt.Println(path)
}
実行結果
$ cd ~/hello
$ go build -o myexe main.go
$ ./myexe
/Users/maku/hello/myexe

go run コマンドで .go ファイルを指定して実行した場合は、内部的にビルドされて生成された実行ファイルのパスが表示されます。

$ go run main.go
/var/folders/g7/08g8xg4x7_lb3k_tgpwwdfmr0000gn/T/go-build9032354/b001/exe/main

応用例として、実行ファイルのあるディレクトリのパスを取得したい場合は、filepath.Dir 関数を組み合わせて使用します。

package main

import (
	"fmt"
	"os"
	"path/filepath"
)

func main() {
	exePath, err := os.Executable()
	if err != nil {
		panic(err)
	}
	exeDir := filepath.Dir(exePath)

	fmt.Println(exePath) //=> /Users/maku/hello/myexe
	fmt.Println(exeDir)  //=> /Users/maku/hello
}

実行ファイルと同じディレクトリにあるリソースファイルのパスを構築したければ、以下のように filepath.Join でパスを繋ぎます。

dataPath := filepath.Join(exeDir, "data.txt") //=> /Users/maku/hello/data.txt

とはいえ、前述の通り、os.Executable が返すパスは、go run main.go のように .go ファイルを指定して実行した場合はおそらく想定外のものになるので、リソースファイルのパスはコマンドライン引数や環境変数で指定するのが無難です。