=Start=
缘由:
刚好最近在学习Go语言,所以想着看能不能学习一下如何用Go语言进行实现——目录遍历有哪些方法,以及相对的最佳实践,方便以后快速参考改写。
正文:
参考解答:
Go 语言中进行目录遍历的原生方法主要是以下3种:
filepath.Walk()
ioutil.ReadDir()
os.File.Readdir()
性能是越底层越高(上层其实是对底层API的封装)。
filepath.Walk()遍历根目录(root)下的文件树,为树中的每个文件或目录(包括根目录)调用walkFn。所有在访问文件和目录时出现的错误都由walkFn过滤。遍历按词法顺序进行,这使得输出是确定的,但对于非常大的目录来说,遍历可能是低效的。filepath.Walk()不会跟进符号链接。
package main import ( "flag" "fmt" "os" "path/filepath" ) // https://rosettacode.org/wiki/Walk_a_directory/Recursively#Go const ( layout = "2006-01-02 15:04:05" ) func VisitFile(fp string, fi os.FileInfo, err error) error { if err != nil { fmt.Println(err) // can't walk here, return nil // but continue walking elsewhere } if fi.IsDir() { return nil // not a file. ignore. } // 过滤输出内容 matched, err := filepath.Match("*.txt", fi.Name()) if err != nil { fmt.Println(err) // malformed pattern return err // this is fatal. } if matched { // fmt.Println(fp) fmt.Printf("Name: %s, ModifyTime: %s, Size: %v\n", fp, fi.ModTime().Format(layout), fi.Size()) } return nil } func main() { var path = flag.String("path", ".", "The path to traverse.") flag.Parse() filepath.Walk(*path, VisitFile) }
filepath.Walk()会自动遍历子目录,但有些时候我们不希望这样,如果只想看当前目录,或手动指定某几级目录中的文件,这个时候,可以使用 ioutil.ReadDir 进行替代。
package main import ( "flag" "fmt" "io/ioutil" "log" ) func main() { var path = flag.String("path", ".", "The path to traverse.") flag.Parse() files, err := ioutil.ReadDir(*path) if err != nil { log.Fatal(err) } for _, file := range files { fmt.Println(file.Name()) } }
几个方法封装的一个演示和对比:
package main import ( "fmt" "io/ioutil" "os" "path/filepath" ) // https://stackoverflow.com/questions/14668850/list-directory-in-go/49196644#49196644 func main() { var ( root string files []string err error ) // root = "/home/manigandan/Desktop/Manigandan/sample" root = "." // filepath.Walk files, err = FilePathWalkDir(root) if err != nil { panic(err) } // ioutil.ReadDir files, err = IOReadDir(root) if err != nil { panic(err) } //os.File.Readdir files, err = OSReadDir(root) if err != nil { panic(err) } for _, file := range files { fmt.Println(file) } } func FilePathWalkDir(root string) ([]string, error) { var files []string err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { if !info.IsDir() { files = append(files, path) } return nil }) return files, err } func IOReadDir(root string) ([]string, error) { var files []string fileInfo, err := ioutil.ReadDir(root) if err != nil { return files, err } for _, file := range fileInfo { files = append(files, file.Name()) } return files, nil } func OSReadDir(root string) ([]string, error) { var files []string f, err := os.Open(root) if err != nil { return files, err } fileInfo, err := f.Readdir(-1) f.Close() if err != nil { return files, err } for _, file := range fileInfo { files = append(files, file.Name()) } return files, nil }
参考链接:
- https://rosettacode.org/wiki/Walk_a_directory/Recursively#Go
- https://stackoverflow.com/questions/14668850/list-directory-in-go/49196644#49196644
=END=
《 “Go语言学习#7-如何进行目录遍历” 》 有 2 条评论
这年头感觉弄独立博客的程序员越来越少了,能坚持写这么多年的人也越来越少了。
Google寻找有效率的go遍历目录的方法发现这片文章,写得不错,感谢
很少发评论,表示一下自己也需要更新一下自己的博客!!
谢谢!一起加油!