如何在Golang Walk提前终止?

如何在Golang Walk提前终止?,go,Go,如果可能的话,让Go的filepath.Walk早点返回的惯用方法是什么 我正在编写一个函数来查找给定名称的嵌套目录。使用filepath.Walk我无法在找到第一个匹配项后立即终止树遍历 func (*RecursiveFinder) Find(needle string, haystack string) (result string, err error) { filepath.Walk(haystack, func(path string, fi os.FileInfo, err

如果可能的话,让Go的
filepath.Walk
早点返回的惯用方法是什么

我正在编写一个函数来查找给定名称的嵌套目录。使用
filepath.Walk
我无法在找到第一个匹配项后立即终止树遍历

func (*RecursiveFinder) Find(needle string, haystack string) (result string, err error) {
    filepath.Walk(haystack, func(path string, fi os.FileInfo, errIn error) (errOut error) {
        fmt.Println(path)

        if fi.Name() == needle {
            fmt.Println("Found " + path)
            result = path
            return nil
        }

        return
    })

    return
}

您应该从walkfunc返回一个错误。为了确保没有返回真正的错误,您可以使用一个已知的错误,比如
io.EOF

func Find(needle string, haystack string) (result string, err error) {

    err = filepath.Walk(haystack, 
      filepath.WalkFunc(func(path string, fi os.FileInfo, errIn error) error {
        fmt.Println(path)

        if fi.Name() == needle {
            fmt.Println("Found " + path)
            result = path
            return io.EOF
        }

        return nil
    }))

    if err == io.EOF {
        err = nil
    }

    return
}
您可以使用定义自己的错误:

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

var stopWalk = errors.New("stop walking")

func find(name, root string) (string, error) {
   var spath string
   e := filepath.Walk(root, func (path string, info os.FileInfo, e error) error {
      if info.Name() == name {
         spath = path
         return stopWalk
      }
      return e
   })
   if e == stopWalk {
      return spath, nil
   }
   return "", e
}
或者您可以使用:


为什么不返回一个错误并停止行走?您可以返回
io.EOF
以确保没有其他错误。展开作为答案…感谢您的回答。我在发布后发现了文档中提到的
filepath.SkipDir()
。您知道返回
io.EOF
SkipDir()
之间是否有任何区别吗?SkipDir()不会停止行走,但会跳转到下一个目录。如果不是递归遍历,效果将是相同的,但我认为最好返回另一个错误。从TFM:
如果返回错误,处理将停止。唯一的例外是当函数返回特殊值SkipDir时。如果函数在目录上调用时返回SkipDir,Walk将完全跳过目录的内容。如果在对非目录文件调用时函数返回SkipDir,Walk将跳过包含目录中的其余文件
import "path/filepath"

func find(pattern string) (string, error) {
   paths, e := filepath.Glob(pattern)
   if paths == nil { return "", e }
   return paths[0], nil
}