如何在Go中模拟/抽象文件系统?

45

我希望能记录我的Go应用程序发出的所有写入/读取底层操作系统的日志,并且(如果可能的话)完全替换文件系统为仅驻留在内存中的文件系统。

这是否可行?怎么做?也许有现成的解决方案吗?

4个回答

47

这是直接从Andrew Gerrand的《关于Go语言你 (可能) 不知道的10件事》中摘录的:

var fs fileSystem = osFS{}

type fileSystem interface {
    Open(name string) (file, error)
    Stat(name string) (os.FileInfo, error)
}

type file interface {
    io.Closer
    io.Reader
    io.ReaderAt
    io.Seeker
    Stat() (os.FileInfo, error)
}

// osFS implements fileSystem using the local disk.
type osFS struct{}

func (osFS) Open(name string) (file, error)        { return os.Open(name) }
func (osFS) Stat(name string) (os.FileInfo, error) { return os.Stat(name) }
为了让这个工作,您需要编写您的代码以接受一个fileSystem参数(可能将其嵌入其他类型中,或者让nil表示默认文件系统)。

2
看起来很有前途,但是直接调用 os.Open 呢?赋值 fs 变量会“悄悄地”影响它们吗? - canni
1
@canni:不,这不会影响直接调用。如果这是你想要的,我认为你将不得不在链接器上做手脚,而我自己从未尝试过。 - Fred Foo
1
这个实现非常聪明,但所有的“文件”都是空的,这使得某些类型的测试变得困难。例如,如果您有一个作为结构体一部分或文件映射的地图的文件,则无法测试正确的文件是否映射到正确的结构体或映射键。 - Dave Rawks
@Paradiesstaub 这是您需要的:用于测试Golang文件系统的示例代码 - icza

34

如果你正在寻找解决测试期间模拟文件系统的问题,可以查看 @spf13 的 Afero 库,https://github.com/spf13/afero。它可以完成已被接受答案所能做的所有事情,但是文档和示例更好。


afero库的基于内存的文件系统(用于测试)非常宽容。一些函数会返回错误,但该错误始终为nil。 - Bren
2
@Bren,我们在生产代码中使用Afero,而不仅仅是用于测试。您能否更详细地解释一下您所说的错误为nil的含义?如果您认为行为不正确,最好在GitHub存储库上提交问题。 - Ryan Walls
1
它似乎并不是io/fs的即插即用替代品。https://github.com/spf13/afero/issues/325 - G. Kashtanov
1
根据对该问题的回复,@G.Kashtanov表示:“您必须将 afero.Fs转换为 afero.IOFS”。链接:https://github.com/spf13/afero/issues/325#issuecomment-1115075828 - Benjamin R

21
您可以使用 testing/fstest 包:
package main
import "testing/fstest"

func main() {
   fs := fstest.MapFS{
      "hello.txt": {
         Data: []byte("hello, world"),
      },
   }
   data, err := fs.ReadFile("hello.txt")
   if err != nil {
      panic(err)
   }
   println(string(data) == "hello, world")
}

https://godocs.io/testing/fstest


3
可以这样添加目录:fstest.MapFS{"tmp": {Mode: fs.ModeDir}} - G. Kashtanov
2
请注意,传递给测试的所有子目录都不得是绝对路径。 例如,以下写法是错误的: fstest.MapFS{"/do/not/use/absolute/paths/no.txt": {}}以下写法是正确的: fstest.MapFS{"relative/path/with/no/leading/slash/ok.txt": {}}我不小心添加了一个绝对路径,这些条目在测试中被省略了。奇怪的是,一个空的“name”目录被添加了进去。 - Bouncing Bit
3
你如何支持测试绝对路径? - Steve

1

只是因为这个问题在谷歌搜索时排名很高:

我不知道如何记录读写日志,但对于仅驻留在内存中的文件系统,我发现了blang/vfs。我没有在生产中使用过,并且它说它是α版,接口可能会更改。自行承担风险。

我想你可以实现它来记录读写操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接