Python中有一个函数 os.walk 很好用,不过感觉Go里面同样功能的函数也十分不错,它也叫 Walk ,属于 path/filepath 包里面的函数,它与Python的不同之处在于,Python会是直接遍历所有目录,而Go的版本则是使用一种 “探索者”的模式,该函数本身并不返回什么内容,而是允许你传入自己的函数用来处理每一次遇到文件时的动作。

type WalkFunc func(path string, info os.FileInfo, err error) error

上面这个就是上面所说的“探索者”的函数类型,我们像下面这么使用它:

package main

import (
    "fmt"
    "os"
    "path/filepath"
)
func explorer(path string, info os.FileInfo, err error) error {
    if err != nil {
        fmt.Printf("ERROR: %v", err)
        return err
    }
    if info.IsDir() {
        fmt.Printf("找到目录: %sn", path)
    } else {
        fmt.Printf("找到文件: %sn", path)
    }
    return nil
}

func main() {
    filepath.Walk("/home/cox/websites/codinuts.csmumu.net/", explorer)
}

我们首先定义一下 filepath.WalkFunc 的具体实现,我上面的示例中,我首先判断是不是目录,如果是目录就打印:“找到目录:『目录路径」”,找到文件就打印:“找到文件:「文件路径」“,有错误的话,打印出错误,然后返回错误,如果没有错误,则返回 nil。之后将该函数传送给 filepath.Walk 之后,它将会在每一次遍历到文件时调用该函数,到现在为止,似乎该函数只能让我们打印出找到的内容而已,没有什么实际用处,其实不然,再看下面这个示例:

package main

import (
    "os"
    "fmt"
    "path/filepath"
)

type Walker struct {
    directories []string
    files       []string
}

func main() {
    walker := new (Walker)
    path := "/home/cox/go/src/github.com/pantao"
    filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
            if err != nil { return err }
            if info.IsDir() {
                walker.directories = append(walker.directories, path)
            } else {
                walker.files = append(walker.files, path)
            }
            return nil
        })
    fmt.Printf("找到 %d 个目录以及 %d 个文件n", len(walker.directories), len(walker.files))
}

在上面的示例中,我创建了一个新的类型 Walker ,它有两人个字段 directories []string 与 files []string 分别用来保存找到的目录和文件,然后让 WalkFunc 去掉用它,不再直接打印出找到的文件,而是将找到的目录和文件都保存到 walker 的字段里面去,以备以后使用。

这个在我的 Amazon S3 Cograndient 工具里面就使用到了,我使用它来获取本地目录的所有文件。

标签: none

评论已关闭