先日、Goのバージョン1.13がリリースされました。そこで、今回は、簡単にGoの新しい機能を紹介し、その後で、ファイル一覧表示を行うプログラムを紹介します。サブディレクトリ以下を含め、すべてのファイルの一覧を取得するには、再帰処理が必要です。どのように書けば良いのか確認してみましょう。

最新リリースのGo1.13について

Go言語の最新版である1.13が先日(2019年9月3日)公開されました。ちょうど1.12の公開から半年後というタイミングでした。互換性に配慮したアップデートなので、1.12以前で作ったプログラムでも、問題なく動かすことができることでしょう。

変更点としては、goコマンドを使ってモジュールをダウンロードする時に、Googleが運用するチェックサムのデータベースを使って認証を行うようになりました。

また、数値リテラルに、2進整数リテラルや、8進整数数リテラル、16進数浮動小数点リテラル、虚数リテラルが追加され、2進数や8進数を手軽に記述できるようになりました。そして、桁の大きな数値を記述する数字セパレータを指定できるようになりました。

print(0b1111)    // 2進数リテラル → 15
print(0o666)     // 8進数リテラル → 438
print(3_000_000) // 数字セパレータ → 3000000

他にも、エラーを扱うパッケージerrorsに新機能が追加され、エラーの発生元を特定しやすくなりました。WebAssemblyも機能追加されています。

より詳しい変更点は、リリースノートに列挙されています。

また、本連載でも基本的に最新版の1.13を用いてプログラムを作っていきます。こちらから各OSごとのインストーラーをダウンロードできます。

ファイルの一覧を取得する方法

さて、今回紹介するのは、ファイルの一覧を取得するプログラムです。Go言語はちょっとしたツールを作るのに便利なプログラミング言語です。ファイル関連のツールを作る機会も多いので、マスターしておきましょう。

最初に簡単なファイルの一覧を取得する方法を見てみましょう。カレントディレクトリにあるファイルやフォルダの一覧を取得して表示してみます。

package main
import (
    "fmt"
    "log"
    "io/ioutil"
)
func main() {
    // カレントディレクトリのファイル一覧を得る
    files, err := ioutil.ReadDir(".")
    if err != nil {
        log.Fatal(err)
    }
    // 取得した一覧を表示
    for _, file := range files {
        fmt.Println(file.Name())
    }
}

上記のプログラムを「files.go」という名前で保存します。そして、コマンドラインから「go run files.go」を実行してみましょう。すると、カレントディレクトリにあるファイルの一覧を取得して表示します。

  • カレントディレクトリのファイル一覧が表示される

    カレントディレクトリのファイル一覧が表示される

指定ディレクトリにあるファイル一覧を取得するのが、ioutil.ReadDir関数です。引数にディレクトリを与えると、string型のスライスを返します。

再帰的にファイル一覧を取得する

上記のプログラムは、単に指定のディレクトリにあるファイルの一覧を表示するだけで、サブディレクトリがあった場合、フォルダの名前が表示されただけでした。次に、特定のフォルダを再帰的に巡回して、ファイルの一覧を表示するプログラムを作ってみましょう。

package main
import (
    "fmt"
    "log"
    "io/ioutil"
    "path/filepath"
)
func main() {
    // カレントディレクトリ以下のファイル一覧を得て出力 --- (*1)
    for _, f := range GetFiles(".") {
        fmt.Println(f)
    }
}
// 再帰的にファイルの一覧を得る --- (*2)
func GetFiles(dir string) []string {
    var result []string
    files, err := ioutil.ReadDir(dir)
    if err != nil {
        log.Fatal(err)
    }
    for _, file := range files {
        fpath := filepath.Join(dir, file.Name())
        if file.IsDir() { // サブディレクトリの一覧を得る --- (*3)
            result = append(result, GetFiles(fpath)...)
            continue
        }
        result = append(result, fpath)
    }
    return result
}

上記のプログラムを「files2.go」という名前で保存します。そして、コマンドラインから「go run files2.go」を実行してみましょう。すると、カレントディレクトリ以下にあるファイルの一覧を再帰的に取得して表示します。

  • カレントディレクトリ以下のすべてのファイル一覧が表示される

    カレントディレクトリ以下のすべてのファイル一覧が表示される

プログラムを確認してみましょう。(*1)の部分で、カレントディレクトリを指定して(*2)で定義したGetFiles関数を呼び出します。(*2)では、ファイルの一覧を取得します。ただし、(*3)の部分でファイル一覧の中にディレクトリがあれば、GetFiles関数を再帰的に呼び出すという仕組みです。

まとめ

以上、今回は、Go1.13の紹介とファイル一覧を取得するプログラムを紹介しました。サブディレクトリを処理する際には、関数の中から同じ関数を呼ぶという再帰処理のテクニックを利用する必要があります。

ところで、なぜ今回ファイル一覧にこだわったのかというと、次回、実際に今回のプログラムを利用したファイル関連ツールを作ってみようと思ったからです。次回もお楽しみに!

自由型プログラマー。くじらはんどにて、プログラミングの楽しさを伝える活動をしている。代表作に、日本語プログラミング言語「なでしこ」 、テキスト音楽「サクラ」など。2001年オンラインソフト大賞入賞、2004年度未踏ユース スーパークリエータ、2010年 OSS貢献者章受賞。技術書も多く執筆している。