LoginSignup
6
5

More than 5 years have passed since last update.

Go言語のpath/filepathパッケージのRel関数について

Posted at

path/filepathパッケージ

これはGoの標準ライブラリです。名前の通りファイルシステムの操作を行うための便利な関数がいくつか利用することができます。このエントリではRel()関数について記述します。

filepath.Rel(basepath, targetpath)

この関数は basepath から targetpath までの相対パスを算出します。引数は string 型になります。基準となるパスを basepath として渡し、 targetpath にいわば求めたい行き先のパスを指定します。返り値は算出された 相対パスエラー の2つです。問題無く相対パスが算出されれば エラーnil が返ります。

利用サンプルその1

sample.go
package main

import (
  "path/filepath"
    "fmt"
    )

func main() {
    basepath := "/a"
      targetpath := "/a/b/c"

        fmt.Println( filepath.Rel(basepath, targetpath) )
}

出力結果は以下のようになります。

$ go run sample.go
b/c <nil>

利用サンプルその2

sample2.go
package main

import (
  "path/filepath"
    "fmt"
    )

func main() {
    basepath := "/a"
      targetpath := "/b/c"

        fmt.Println( filepath.Rel(basepath, targetpath) )
}

さて、ここで上記のようにしたらどうなるでしょう…。
結果は以下のようになりました。

$ go run sample2.go
../b/c <nil>

そう!こうなるんですね。
ここで、頭の悪い私は出力結果/b/c となるのかなと思いました。なぜかというと、基準となるパスを /a と指定し、行き先を /b/c と指定しているので、 /b/c が基準となるパス /a に含まれていると勘違いしていたからです。しかし、指定しているパスは /a/b/c ではなく /b/c ですから、当然得られる結果は ../b/c となるわけですね。

利用サンプルその3

sample3.go
package main

import (
  "path/filepath"
    "fmt"
    )

func main() {
    basepath := "/a"
      targetpath := "./b/c"

        fmt.Println( filepath.Rel(basepath, targetpath) )
}

さて、これはどうなるでしょうか?

$ go run sample3.go
 Rel: can't make b/c relative to /a

エラーになりました。理由は、 . これですね。つまりカレントディレクトリを指定しているからなんです。今回の場合Go言語はカレントディレクトリを知りません。基準となるパス /a を自動的にカレントディレクトリとしてはみなしてくれないんですね。もちろんですが、ワーキングディレクトリともみなしてくれません。Go言語は行き先の行き方がわからんのでエラーとなるわけですね。

※ちなみにエラーだと、相対パスには空文字列が入るみたいですね。

上記の問題は基準となるパスをカレントディレクトリからの相対パスにしてあげると解決します。

sample4.go
 package main

 import (
   "path/filepath"
     "fmt"
     )

 func main() {
     basepath := "./a"
       targetpath := "./b/c"

         fmt.Println( filepath.Rel(basepath, targetpath) )
 }

出力結果

 $ go run sample4.go
 ../b/c <nil>

参考までに

今回紹介させていただいた Rel 関数を使って得られた出力結果の相対パスは、同じパッケージで含まれる Join 関数を使うと分かり易いかもしれません。

filepath.Join(basepath, filepath(basepath, targetpath))

これから得られる結果は必ず targetpath と同じになります。

感想

Go言語の公式ドキュメントは英語なのです。他の言語もたいていそうです。エンジニアとして成長するためには、英語力は必須というわけですね。英語頑張らないといけないなと思わされました。

The Go Programming Language

6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5