我打算如何在Go中使用Filepath.Walk?

Joe*_*Joe 18 closures go

filepath.Walk函数采用函数回调.这是直接函数,没有上下文指针.当然,一个主要的用例Walk是走一个目录并根据它进行一些操作,参考更广泛的上下文(例如将每个文件输入到表中).

如果我在C#中编写它,我将使用一个对象(可以指向上下文中的对象的字段)作为回调(使用给定的回调方法),因此该对象可以封装Walk从中调用的上下文.

(编辑:用户" usr "表示闭包方法也发生在C#中)

如果我在C中写这个,我会要求一个函数和一个上下文指针,void *因此该函数有一个上下文指针,它可以传递给Walk函数并将其传递给回调函数.

但Go只有函数参数,没有明显的上下文指针参数.

(如果我设计了这个函数,我会把一个对象作为一个回调而不是一个函数,符合接口FileWalkerCallback或其他什么,并callback(...)在该接口上放置一个方法.然后,消费者可以在传递它之前将任何上下文附加到对象到Walk.)

我能想到的唯一方法是捕获回调函数中外部函数的闭包.这是我如何使用它:

func ScanAllFiles(location string, myStorageThing *StorageThing) (err error) {
    numScanned = 0

    // Wrap this up in this function's closure to capture the `corpus` binding.
    var scan = func(path string, fileInfo os.FileInfo, inpErr error) (err error) {
        numScanned ++

        myStorageThing.DoSomething(path)
    }

    fmt.Println("Scan All")

    err = filepath.Walk(location, scan)

    fmt.Println("Total scanned", numScanned)

    return
}
Run Code Online (Sandbox Code Playgroud)

在这个例子中,我创建了回调函数,因此它的闭包包含变量numScannedmyStorageThing.

这对我来说不合适.我是否认为这感觉很奇怪,或者我只是习惯写Go?如何filepath.Walk以一种回调引用更广泛的上下文的方式使用该方法?

Son*_*nia 15

你正确地做到了.您可以考虑两种小变化.一个是您可以用下划线替换未使用参数的名称.因此,在您仅使用路径的示例中,签名可以读取

func(path string, _ os.FileInfo, _ error) error
Run Code Online (Sandbox Code Playgroud)

它节省了一点点打字,清理了一点代码,并清楚地表明你没有使用参数.此外,特别是对于小函数,通常跳过将函数文本赋值给变量,并直接将其用作参数.你的代码最终会阅读,

err = filepath.Walk(location, func(path string, _ os.FileInfo, _ error) error {
    numScanned ++

    myStorageThing.DoSomething(path)
})
Run Code Online (Sandbox Code Playgroud)

这样可以清理一下范围,明确表示您只使用了一次封闭.