[インデックス 11986] ファイルの概要
このコミットは、Go言語の標準ライブラリであるpath/filepath
パッケージのfilepath.Walk
関数の使用例を、Go 1の公式ドキュメントに追加するものです。具体的には、filepath.Walk
の動作を説明するHTMLドキュメント(doc/go1.html
とdoc/go1.tmpl
)に、新しいGoプログラムの例(doc/progs/go1.go
)を埋め込むことで、ユーザーがfilepath.Walk
の挙動、特にディレクトリのスキップ(filepath.SkipDir
)の方法を視覚的に理解できるように改善しています。
コミット
- コミットハッシュ:
91672686da0af0d2e21b022c36b9977a78ec490f
- 作者: Mike Rosset mike.rosset@gmail.com
- 日付: 2012年2月17日金曜日 12:45:55 +1100
- コミットメッセージ:
doc: provide example filepath.Walk for go1 R=golang-dev, r, r CC=golang-dev https://golang.org/cl/5674067
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/91672686da0af0d2e21b022c36b9977a78ec490f
元コミット内容
doc: provide example filepath.Walk for go1
R=golang-dev, r, r
CC=golang-dev
https://golang.org/cl/5674067
変更の背景
Go言語の初期バージョンであるGo 1のリリースに向けて、ドキュメントの充実が図られていました。path/filepath
パッケージのWalk
関数は、ファイルシステムを再帰的に走査するための非常に強力なツールですが、その使用方法、特に特定のディレクトリをスキップするfilepath.SkipDir
の挙動は、初心者には直感的ではない場合があります。
このコミットの背景には、filepath.Walk
のドキュメントに具体的なコード例が不足しており、ユーザーがこの関数を効果的に利用するための理解を深める必要があったという課題があります。既存のドキュメントには「TODO: add an example?」というコメントがあり、例の追加が求められていたことが示されています。この変更は、その要望に応え、Go 1のドキュメントの品質とユーザーフレンドリーさを向上させることを目的としています。
前提知識の解説
このコミットを理解するためには、以下のGo言語の概念と標準ライブラリに関する知識が必要です。
-
path/filepath
パッケージ:- Go言語でファイルパスを操作するためのユーティリティを提供するパッケージです。プラットフォーム固有のパス区切り文字(Windowsの
\
、Unix系の/
)を抽象化し、クロスプラットフォームなパス操作を可能にします。 filepath.Walk(root string, walkFn WalkFunc) error
: 指定されたroot
パスから開始して、ファイルツリーを再帰的に走査する関数です。walkFn
というコールバック関数を、走査中に見つかった各ファイルやディレクトリに対して呼び出します。WalkFunc
型:filepath.Walk
に渡されるコールバック関数の型定義です。type WalkFunc func(path string, info os.FileInfo, err error) error
path
: 現在走査しているファイルまたはディレクトリのパス。info
: そのファイルまたはディレクトリのos.FileInfo
インターフェース。ファイル名、サイズ、パーミッション、変更時刻などの情報を提供します。err
:filepath.Walk
がpath
にアクセスしようとした際に発生したエラー。エラーがない場合はnil
。WalkFunc
がnil
以外のエラーを返すと、filepath.Walk
はそのエラーを返して走査を停止します。
filepath.SkipDir
:WalkFunc
がこの特殊なエラー値を返すと、filepath.Walk
は現在のディレクトリの内容をスキップし、そのディレクトリの兄弟要素の走査を続行します。これは、特定のサブディレクトリを処理対象から除外したい場合に非常に便利です。
- Go言語でファイルパスを操作するためのユーティリティを提供するパッケージです。プラットフォーム固有のパス区切り文字(Windowsの
-
os
パッケージ:- オペレーティングシステム機能へのアクセスを提供するパッケージです。
os.FileInfo
インターフェース: ファイルやディレクトリのメタデータ(名前、サイズ、モード、変更時刻など)を抽象的に表現するためのインターフェースです。filepath.Walk
のWalkFunc
に渡されるinfo
引数として使用されます。
-
log
パッケージ:- ログメッセージを出力するためのシンプルなパッケージです。
log.Println(v ...interface{})
: 引数をデフォルトのフォーマットで標準エラー出力に書き込み、改行を追加します。log.Fatal(v ...interface{})
:Println
と同様にログを出力した後、os.Exit(1)
を呼び出してプログラムを終了します。
-
Goのドキュメント生成:
- Goのドキュメントは、Goのソースコード内のコメントや、専用のMarkdown/HTMLファイルから生成されます。このコミットでは、
doc/go1.html
とdoc/go1.tmpl
がGo 1のドキュメントの一部であり、doc/progs/go1.go
はドキュメントに埋め込まれるコード例を格納するファイルです。 {{code "progs/go1.go" /STARTWALK/ /ENDWALK/}}
のような構文は、Goのドキュメントツールがprogs/go1.go
ファイルから/STARTWALK/
と/ENDWALK/
マーカーで囲まれたコードブロックを抽出し、それをHTMLドキュメントに埋め込むためのディレクティブです。これにより、ドキュメント内のコード例と実際の実行可能なコードが同期され、常に最新の状態に保たれます。
- Goのドキュメントは、Goのソースコード内のコメントや、専用のMarkdown/HTMLファイルから生成されます。このコミットでは、
技術的詳細
このコミットは、Go 1のドキュメントにおけるfilepath.Walk
関数の説明セクションに、具体的なコード例を組み込むことで、その理解を深めることを目的としています。
変更は主に以下の3つのファイルにわたります。
-
doc/go1.html
:- このファイルは、Go 1のドキュメントのHTMLバージョンです。
- 以前は
filepath.Walk
の説明の後に「TODO: add an example?」というコメントと、赤字で例の追加を促すプレースホルダーがありました。 - このコミットでは、そのプレースホルダーが削除され、代わりに
doc/progs/go1.go
から抽出されたfilepath.Walk
の具体的なGoコード例が<pre>
タグ内に直接埋め込まれています。 - また、
SkipDir
の参照が単なるコードスニペットから、/pkg/path/filepath/#variables
へのハイパーリンクを含むfilepath.SkipDir
に変更され、より公式なドキュメントへの参照が提供されています。
-
doc/go1.tmpl
:- このファイルは、Go 1のドキュメントのテンプレートファイルであり、HTMLドキュメントを生成するための元となるものです。
doc/go1.html
と同様に、「TODO: add an example?」のコメントとプレースホルダーが削除されました。- 最も重要な変更は、
{{code "progs/go1.go" /STARTWALK/ /ENDWALK/}}
というテンプレートディレクティブが追加されたことです。これは、Goのドキュメント生成システムに対し、doc/progs/go1.go
ファイル内のSTARTWALK
とENDWALK
というコメントマーカーで囲まれたコードブロックを抽出し、この位置に挿入するように指示します。これにより、ドキュメントのHTMLバージョンとテンプレートバージョンの両方で、動的にコード例が埋め込まれるようになります。 SkipDir
の参照もfilepath.SkipDir
に更新され、パッケージ内の変数へのリンクが追加されています。
-
doc/progs/go1.go
:- このファイルは、Go 1のドキュメント内で使用される様々なコード例をまとめたGoプログラムです。
- 新しい
func walkExample()
関数が追加されました。この関数はfilepath.Walk
の具体的な使用例を含んでいます。 main
関数内でwalkExample()
が呼び出されるように変更され、この例が実行可能なプログラムの一部として統合されました。path/filepath
パッケージがインポートリストに追加されました。// STARTWALK OMIT
と// ENDWALK OMIT
という特殊なコメントがwalkExample
関数の前後に追加されています。これらは、doc/go1.tmpl
で使用されている{{code ...}}
ディレクティブが、この特定のコードブロックを正確に抽出するために使用するマーカーです。OMIT
は、ドキュメント生成時にこれらのコメント行自体は出力しないことを示します。
これらの変更により、Go 1のドキュメントはfilepath.Walk
の機能とfilepath.SkipDir
の利用方法を、実際の動作するコード例を通じてより明確に説明できるようになりました。
コアとなるコードの変更箇所
このコミットのコアとなるコードの変更は、主にdoc/progs/go1.go
ファイルに新しいwalkExample
関数が追加された点です。
--- a/doc/progs/go1.go
+++ b/doc/progs/go1.go
@@ -12,6 +12,7 @@ import (
"fmt"
"log"
"os"
+ "path/filepath"
"testing"
"time"
"unicode"
@@ -28,6 +29,7 @@ func main() {
runType()
errorExample()
timePackage()
+ walkExample()
osIsExist()
}
@@ -183,6 +185,25 @@ func timePackage() {
sleepUntil(time.Now().Add(123 * time.Millisecond))\n}\n
+func walkExample() {
+ // STARTWALK OMIT
+ markFn := func(path string, info os.FileInfo, err error) error {
+ if path == "pictures" { // Will skip walking of directory pictures and its contents.
+ return filepath.SkipDir
+ }
+ if err != nil {
+ return err
+ }
+ log.Println(path)
+ return nil
+ }
+ err := filepath.Walk(".", markFn)
+ if err != nil {
+ log.Fatal(err)
+ }
+ // ENDWALK OMIT
+}
+
func initializationFunction(c chan int) {
c <- 1
}
コアとなるコードの解説
追加されたwalkExample
関数は、filepath.Walk
の典型的な使用パターンを示しています。
func walkExample() {
// STARTWALK OMIT
markFn := func(path string, info os.FileInfo, err error) error {
if path == "pictures" { // Will skip walking of directory pictures and its contents.
return filepath.SkipDir
}
if err != nil {
return err
}
log.Println(path)
return nil
}
err := filepath.Walk(".", markFn)
if err != nil {
log.Fatal(err)
}
// ENDWALK OMIT
}
-
markFn
の定義:filepath.Walk
に渡すWalkFunc
型の匿名関数markFn
を定義しています。- この関数は、
path
(現在のファイル/ディレクトリのパス)、info
(ファイル情報)、err
(エラー)の3つの引数を受け取ります。
-
ディレクトリのスキップ条件:
if path == "pictures" { return filepath.SkipDir }
- これがこの例の最も重要な部分です。もし現在のパスが文字列
"pictures"
と一致した場合(つまり、カレントディレクトリ直下のpictures
という名前のディレクトリに遭遇した場合)、markFn
はfilepath.SkipDir
を返します。 filepath.SkipDir
が返されると、filepath.Walk
はpictures
ディレクトリとその中のすべての内容の走査をスキップし、pictures
ディレクトリの兄弟要素(同じ階層にある他のファイルやディレクトリ)の走査を続行します。これにより、特定のサブツリーを効率的に無視できます。
- これがこの例の最も重要な部分です。もし現在のパスが文字列
-
エラーハンドリング:
if err != nil { return err }
filepath.Walk
がpath
にアクセスする際にエラーが発生した場合(例: 権限がない、ファイルが存在しないなど)、そのエラーをmarkFn
に渡します。markFn
がこのエラーをそのまま返すと、filepath.Walk
は直ちに走査を中止し、そのエラーを呼び出し元に返します。これは、ファイルシステム走査中に致命的な問題が発生した場合の標準的なエラー処理パターンです。
-
パスの出力:
log.Println(path)
- エラーがなく、かつディレクトリがスキップされない場合、現在のファイルまたはディレクトリのパスを標準出力にログとして出力します。これにより、
filepath.Walk
が実際にどのパスを訪れたかを確認できます。
- エラーがなく、かつディレクトリがスキップされない場合、現在のファイルまたはディレクトリのパスを標準出力にログとして出力します。これにより、
-
正常終了:
return nil
markFn
がnil
を返すと、filepath.Walk
は走査を続行します。
-
filepath.Walk
の呼び出し:err := filepath.Walk(".", markFn)
- カレントディレクトリ(
.
)からファイルシステム走査を開始し、定義したmarkFn
をコールバックとして使用します。
- カレントディレクトリ(
-
メインのエラーハンドリング:
if err != nil { log.Fatal(err) }
filepath.Walk
関数自体がエラーを返した場合(例:markFn
がエラーを返して走査が中止された場合)、そのエラーをlog.Fatal
で出力し、プログラムを終了します。
この例は、filepath.Walk
の基本的な使い方、WalkFunc
の構造、そして特にfilepath.SkipDir
を使って特定のサブディレクトリを効率的にスキップする方法を明確に示しています。
関連リンク
- Go CL (Change List) 5674067: https://golang.org/cl/5674067
参考にした情報源リンク
- 特になし。コミット内容とGo言語の標準ライブラリの知識に基づいて解説を生成しました。