目標
Base()のアルゴリズムを理解する。
ドキュメント
Base returns the last element of path. Trailing path separators are removed before extracting the last element. If the path is empty, Base returns ".". If the path consists entirely of separators, Base returns a single separator.
パスの最後の要素を返す。引数が空文字のときは"."を返し、区切り文字のみのときは1つだけの区切り文字を返す。
リーディング
func Base(path string) string {
return filepathlite.Base(path)
}
filepathliteってなんだろうか。"internal/filepathlite"がimportされていたので見てみる。
filepathliteのBase()を見る
// Base is filepath.Base.
func Base(path string) string {
if path == "" {
return "."
}
// Strip trailing slashes.
for len(path) > 0 && IsPathSeparator(path[len(path)-1]) {
path = path[0 : len(path)-1]
}
// Throw away volume name
path = path[len(VolumeName(path)):]
// Find the last element
i := len(path) - 1
for i >= 0 && !IsPathSeparator(path[i]) {
i--
}
if i >= 0 {
path = path[i+1:]
}
// If empty now, it had only slashes.
if path == "" {
return string(Separator)
}
return path
}
最初に、引数pathが空である場合は"."を返す。つぎにpathの末尾の区切り文字(sepとする)を除き、pathの後ろから順番にsepとなる文字を探して最初からsepまでの文字を除く。このアルゴリズムでpathの最後の要素を返すという仕様を満たす。さらにpathが空であれば1つのsepを返すことで、pathがsepのみを含むときに1つのsepを返すという仕様を満たす。
なぜfilepathではなくfilepathliteで実装されているのだろうか。
filepathliteで実装されている理由の予想
ソースファイルのコメント
// Package filepathlite implements a subset of path/filepath,
// only using packages which may be imported by "os".
filepathlite/path.goの冒頭コメントによれば、"os"パッケージにインポートされるパッケージのみを使っているとのこと。
コミットログ1
all: rename internal/safefilepath to internal/filepathlite
The safefilepath package was originally added to contain the FromFS function. We subsequently added FromFS to path/filepath as Localize. The safefilepath package now exists only to permit the os package to import Localize.
Rename safefilepath to filepathlite to better indicate that it's a low-dependency version of filepath.
出典: golangのコミットログ
要約: safefilepathパッケージはosパッケージがLocalizeをインポートするためだけに存在していたが、filepathパッケージにもLocalizeが追加されているのでsafefilepathがfilepathの低依存バージョンであることをより明確に示すために名前を変更する。
コミットログ2
path/filepath, internal/filepathlite: move parts of filepath to filepathlite
The path/filepath package needs to depend on the os package to
implement Abs, Walk, and other functions. Move the implementation
of purely lexical functions from path/filepath into
internal/filepathlite, so they can be used by os and
other low-level packages.
出典: golangのコミットログ
要約: filepathはosパッケージに依存しているAPIがあるが、filepathの字句解析的な関数をfilepathliteに移動することで、osパッケージやその他の低レベルパッケージからインポートできるようにする。
理由の考察
osからfilepathパッケージをインポートするとos->filepath->osという循環依存がありできない。filepathのosに依存しないパッケージを別のパッケージに移動することで、osから元filepathのAPIを使えるようにするため。
テストを見る
次回やる。
まとめ
filepath.Base()のアルゴリズムについて理解した。そしてfilepathliteの存在理由についても知ることができ、そこから多くのことを学べたと思う。
まず学んだのは、GitHubのHistoryでコミットログを遡るリサーチ技術。コードの背景を理解するための強力な方法を知ることができた。
そして、コミットメッセージの書き方。具体的な背景や変更の意図が丁寧に説明されていて、とにかく分かりやすかった。自分は(個人開発という言い訳もあり)いつも1行しか書いていないので、見習うべきだと感じた。
最後に、循環依存の解消方法。関数を何らかの基準でグループ分けし、別パッケージにまとめるという具体的なアプローチを知れた。