再回帰とは、
関数自身から関数自身を呼び出す、無限入れ子です。
主に階層構造、フォルダーの検索によく使われます。
fileTools.go
import (
"os"
"path/filepath"
)
func findFiles(find string, dir string, deep int) ([]string, error) {
var fulldir string
var results []string
fulldir, err := filepath.Abs(dir)
if err != nil {
return results, err
}
var _findFiles func(find string, dir string, deep int) ([]string, error)
_findFiles = func(find string, dir string, deep int) ([]string, error) {
var results []string
fulldir, err := filepath.Abs(dir)
if err != nil {
return results, err
}
files, err := os.ReadDir(fulldir)
if err != nil {
return results, err
}
var childFind bool
if deep != 0 {
childFind = true
}
childDeep := deep
if deep > 0 {
childDeep--
}
for _, f := range files {
fullName := filepath.Join(fulldir, f.Name())
if f.IsDir() {
if childFind {
files, _ := _findFiles(find, fullName, childDeep)
for i := range files {
results = append(results, files[i])
}
}
} else {
if len(find) > 0 {
if ok, _ := filepath.Match(find, f.Name()); ok {
results = append(results, fullName)
}
} else {
results = append(results, fullName)
}
}
}
return results, nil
}
results, err = _findFiles(find, fulldir, deep)
if err != nil {
return results, err
}
return results, nil
}
解説
Go言語では、関数の中に無名関数を宣言できます。
無名関数は、「func(引数)」のように関数名を宣言しません。
_findFiles = func(find string, dir string, deep int) ([]string, error) {...}
Go言語では、関数を呼び出すには、関数名が必要なため、関数を変数として先に宣言しておきます。
var _findFiles func(find string, dir string, deep int) ([]string, error)
再回帰は、無名関数の必要は無いが、今回のように親関数と子関数が異なる場合、子関数を独立させると、間違って子関数を使ってしまう場合があります。
公開したくない関数は、無名関数として埋め込んでしまいます。
この findFiles関数の使い方
引数1: find は、ワイルドカードが使えます。
※注意: "*.xlsx"は Excelファイルです。
引数2: dir は、検索したいパスです。
※注意: "../"は、現在の親フォルダーです。
引数3: deep は、-1:制限なし, 0:このフォルダーのみ, 1以上:深さ指定
main.go
func main() {
files, err := findFiles("*.xlsx", "../", -1)
if err != nil {
return
}
for i := range files {
fmt.Println(i, files[i])
}
}