使用文件路径在 Go 中搜索文件
Search for file in Go using filepath
我正在尝试使用 Go 在目录中查找文件。我正在使用文件路径包中的 Walk 函数。在 findFile 函数中,我正在获取文件并将其分配给正在传递的文件的指针。但这似乎不起作用,调用 findFile 后 file 的值仍然为 nil。如果我做错了什么或者这种方法不正确,请指教。
func example() {
var file *os.File
err = filepath.Walk("uploads", findFile(fileId, file))
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
}
func findFile(fileId string, file *os.File) func(path string, info os.FileInfo, err error) error {
return func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() && isFileMatching(info.Name(), fileId) {
file, err = os.Open(path)
if err != nil {
return err
}
}
return nil
}
}
你改变的是指针变量的值,而不是指针指向的值。
应该是:
f, err := os.Open(path)
if err != nil {
return err
}
*file = *f
注:
*file = *f
实际上是一个os.File
.
的副本
这不是一个好的做法。您可能需要考虑为此类工作使用通道(和协程)。
并且您可能还想检查是否只有一个路径可以通过 isFileMatching
,或者是文件描述符泄漏(未关闭打开的文件)。
关于之前的回答可以使用slice来收集文件,不会复制,最后可以全部关闭。
func example() {
var files []*os.File
err := filepath.Walk("uploads", findFile(fileId, &files))
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
}
func findFile(fileId string, files *[]*os.File) func(path string, info os.FileInfo, err error) error {
return func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() && isFileMatching(info.Name(), fileId) {
file, err := os.Open(path)
if err != nil {
return err
}
*files = append(*files, file)
}
return nil
}
}
另一种选择是filepath.WalkDir
:
package main
import (
"errors"
"io/fs"
"os"
"path/filepath"
)
func open(root, name string) (*os.File, error) {
var f *os.File
filepath.WalkDir(root, func(s string, d fs.DirEntry, e error) error {
if e != nil { return e }
if d.Name() != name { return nil }
f, e = os.Open(s)
if e != nil { return e }
return errors.New("found")
})
if f == nil {
return nil, errors.New("not found")
}
return f, nil
}
func main() {
f, e := open(`C:\go`, "path.go")
if e != nil {
panic(e)
}
defer f.Close()
println(f.Name())
}
我正在尝试使用 Go 在目录中查找文件。我正在使用文件路径包中的 Walk 函数。在 findFile 函数中,我正在获取文件并将其分配给正在传递的文件的指针。但这似乎不起作用,调用 findFile 后 file 的值仍然为 nil。如果我做错了什么或者这种方法不正确,请指教。
func example() {
var file *os.File
err = filepath.Walk("uploads", findFile(fileId, file))
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
}
func findFile(fileId string, file *os.File) func(path string, info os.FileInfo, err error) error {
return func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() && isFileMatching(info.Name(), fileId) {
file, err = os.Open(path)
if err != nil {
return err
}
}
return nil
}
}
你改变的是指针变量的值,而不是指针指向的值。
应该是:
f, err := os.Open(path)
if err != nil {
return err
}
*file = *f
注:
*file = *f
实际上是一个os.File
.
这不是一个好的做法。您可能需要考虑为此类工作使用通道(和协程)。
并且您可能还想检查是否只有一个路径可以通过 isFileMatching
,或者是文件描述符泄漏(未关闭打开的文件)。
关于之前的回答可以使用slice来收集文件,不会复制,最后可以全部关闭。
func example() {
var files []*os.File
err := filepath.Walk("uploads", findFile(fileId, &files))
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
}
func findFile(fileId string, files *[]*os.File) func(path string, info os.FileInfo, err error) error {
return func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() && isFileMatching(info.Name(), fileId) {
file, err := os.Open(path)
if err != nil {
return err
}
*files = append(*files, file)
}
return nil
}
}
另一种选择是filepath.WalkDir
:
package main
import (
"errors"
"io/fs"
"os"
"path/filepath"
)
func open(root, name string) (*os.File, error) {
var f *os.File
filepath.WalkDir(root, func(s string, d fs.DirEntry, e error) error {
if e != nil { return e }
if d.Name() != name { return nil }
f, e = os.Open(s)
if e != nil { return e }
return errors.New("found")
})
if f == nil {
return nil, errors.New("not found")
}
return f, nil
}
func main() {
f, e := open(`C:\go`, "path.go")
if e != nil {
panic(e)
}
defer f.Close()
println(f.Name())
}