如何在Golang的Walk函数中提前终止执行?

huangapple go评论82阅读模式
英文:

How to terminate early in Golang Walk?

问题

如果可能的话,使用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
}
英文:

What's the idiomatic way, if possible, of having Go's filepath.Walk return early?

I'm writing a function to find a nested directory of a given name. Using filepath.Walk I can't see a way of terminating the tree-walking as soon as I find the first match.

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
}

答案1

得分: 17

你应该从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
}
英文:

You should return an error from your walkfunc. To make sure no real error has been returned, you can just use a known error, like 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
}

答案2

得分: 0

你可以使用errors.New来定义自己的错误:

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

var stopWalk = errors.New("停止遍历")

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
}

或者你可以使用filepath.Glob

import "path/filepath"

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

You can use errors.New to define your own error:

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
}

Or you can use filepath.Glob:

import "path/filepath"

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

huangapple
  • 本文由 发表于 2016年4月19日 16:48:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/36713248.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定