【问题标题】:How am I meant to use Filepath.Walk in Go?我如何在 Go 中使用 Filepath.Walk?
【发布时间】:2012-07-04 22:34:27
【问题描述】:

filepath.Walk 函数接受函数回调。这是没有上下文指针的直接函数。当然,Walk 的一个主要用例是遍历一个目录并基于它采取一些行动,并参考更广泛的上下文(例如,将每个文件输入到一个表中)。

如果我在 C# 中编写此代码,我将使用一个对象(具有可以指向上下文中对象的字段)作为回调(具有给定的回调方法),以便对象可以封装 @ 987654325@ 被调用。

(编辑:用户“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
}

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

这对我来说是错误的。我认为这感觉很奇怪是对的,还是我只是习惯了写 Go? filepath.Walk 方法的使用目的是如何让回调引用更广泛的上下文?

【问题讨论】:

  • 如果你想得到关于 Go 成语这样的问题的几乎即时回复,你应该将它发布到开发团队和贡献者非常活跃的 golang 组:groups.google.com/group/golang-nuts。他们是一个很棒的支持。
  • 不是即时的。我有一个解决方案。这更像是一种“最佳实践”。我可能会在 google 群组上发帖,但有消息告诉我我需要一个 google 帐户...
  • 您确实需要一个谷歌帐户。但你也会很快得到回复。这是一个非常活跃的群体。

标签: closures go


【解决方案1】:

你这样做是对的。您可以考虑两种小变化。一种是您可以用下划线替换未使用参数的名称。因此,在您仅使用路径的示例中,签名可以读取

func(path string, _ os.FileInfo, _ error) error

它节省了一点打字,清理了一点代码,并清楚地表明您没有使用该参数。此外,特别是对于小型函数,通常跳过将函数文字分配给变量,而直接将其用作参数。您的代码最终会读取,

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

    myStorageThing.DoSomething(path)
})

这稍微清理了作用域,清楚地表明您只使用了一次闭包。

【讨论】:

  • 不错!让人想起 JavaScript(不确定这是否是一件好事)。谢谢。
  • return nil 好像不见了
【解决方案2】:

作为一名 C# 程序员,我可以说这正是 .NET 中的这种 API 的使用方式意味着。我们鼓励您使用闭包,不鼓励您使用字段创建显式类,因为这只会浪费您的时间。

由于 Go 支持闭包,我会说这是使用此 API 的正确方法。我看不出有什么问题。

【讨论】:

  • 我写 C# 已经很久了(嗯,3 年),但我记得我经常使用“传递回调对象”,即使只是用于单元测试目的。但我想不同的任务需要不同的风格。
  • 我猜三年前的闭包对 C# 来说还是个新手。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-09-11
  • 2010-12-15
  • 1970-01-01
  • 1970-01-01
  • 2011-08-18
  • 2018-01-15
  • 2015-10-12
相关资源
最近更新 更多