🛣️

Goでワーキングディレクトリが異なるときに同じファイルにアクセスする

2024/02/02に公開

個人で Go と firebase を使ったアプリケーションを開発していて、アカウント情報が含まれた json ファイルを読み込む必要がありました。
その際、ローカルでのアプリケーションサーバ実行時はファイルにアクセスできていたのにエディタ (vscode) でのデバッグテスト実行時にはファイルにアクセスできない事象が起きました。
今回はその時の解決策を書きます。
今回は firebase の初期化時の事例ですが、ワーキングディレクトリが異なる複数の環境において同じファイルにアクセスしたい場合には応用可能だと思います。

解決策

hoge.go
import (
	"context"
	"path/filepath"
	"runtime"

	firebase "firebase.google.com/go"
	"google.golang.org/api/option"
)

func init() {
    // 実行中ファイルのフルパスを取得
    _, exPath, _, _ := runtime.Caller(0)
    // 実行中ファイルのディレクトリを取得
    wd := filepath.Dir(exPath)
    certainPath := filepath.Join(wd, "path/to/hoge-firebase-adminsdk.json")

    opts := option.WithCredentialFile(certainPath)
    firebaseApp, err := firebase.NewApp(context.Background(), nil, opts)
    ...
}
  1. アクセスしたいファイルにアクセスする処理を行っているファイル (ここでは hoge.go) で、実行ファイルのフルパスを取得します。
  2. 実行ファイルからアクセスしたいファイルへの絶対パスを生成し、そのパスにアクセスします。

やってることはこれだけです。
ワーキングディレクトリが異なるので、実行ファイル中で都度そのファイルのフルパスを取得し、そこからアクセス対象のファイルへの絶対パスを作るというだけになります。
runtime.Caller()filepath.Dir()について一応補足します。

runtime.Caller()

呼び出し元の goroutine のスタック上の関数呼び出しに関するファイルと行番号の情報を報告する (公式ドキュメント) メソッドだそうです。
実行ファイルのパス以外の情報や、メソッド呼び出し箇所の行数も取得できるみたい。

filepath.Dir()

これは、指定したパスのディレクトリ (ファイルまで指定している場合はそのファイルが位置するディレクトリ) を取得してくれるメソッドらしいです (公式ドキュメント)。
filepathパッケージにはDir()の他にもパスを整形する色々なメソッドも含まれているよう。

参考

GitHubで編集を提案

Discussion