我正在io/ioutil阅读一个小文本文件:
fileBytes, err := ioutil.ReadFile("/absolute/path/to/file.txt")
Run Code Online (Sandbox Code Playgroud)
这样做很好,但这不是完全可移植的.在我的例子中,我要打开的文件在我的GOPATH中,例如:
/Users/matt/Dev/go/src/github.com/mholt/mypackage/data/file.txt
Run Code Online (Sandbox Code Playgroud)
由于data文件夹与源代码一起使用,我只想指定相对路径:
data/file.txt
Run Code Online (Sandbox Code Playgroud)
但后来我得到了这个错误:
恐慌:打开data/file.txt:没有这样的文件或目录
如何使用相对路径打开文件,特别是如果它们与我的Go代码一起使用?
Mat*_*att 74
嗯...... path/filepath包装有Abs()哪些我需要的东西(到目前为止)虽然有点不方便:
absPath, _ := filepath.Abs("../mypackage/data/file.txt")
Run Code Online (Sandbox Code Playgroud)
然后我absPath用来加载文件,它工作正常.
请注意,在我的情况下,数据文件位于与main我运行程序的包不同的包中.如果它都在同一个包中,我会删除前导../mypackage/.由于该路径显然是相对的,因此不同的程序将具有不同的结构并且需要相应地调整.
如果有更好的方法将外部资源与Go程序一起使用并保持其可移植性,请随时提供另一个答案.
spe*_*oly 31
这似乎工作得很好:
import "os"
import "io/ioutil"
pwd, _ := os.Getwd()
txt, _ := ioutil.ReadFile(pwd+"/path/to/file.txt")
Run Code Online (Sandbox Code Playgroud)
我写了gobundle来解决这个问题.它从数据文件生成Go源代码,然后将其编译到二进制文件中.然后,您可以通过类似VFS的图层访问文件数据.它完全可移植,支持添加整个文件树,压缩等.
缺点是您需要一个中间步骤来从源数据构建Go文件.我通常使用make来做这件事.
这是你如何迭代一个包中的所有文件,读取字节:
for _, name := range bundle.Files() {
r, _ := bundle.Open(name)
b, _ := ioutil.ReadAll(r)
fmt.Printf("file %s has length %d\n", name, len(b))
}
Run Code Online (Sandbox Code Playgroud)
您可以在我的GeoIP包中看到它的一个真实示例.的Makefile生成的代码,并geoip.go使用该VFS.
从Go 1.16开始,你可以使用embed包。这允许您将文件嵌入到正在运行的 go 程序中。
给定文件结构:
-- main.go
-- data
\- file.txt
Run Code Online (Sandbox Code Playgroud)
您可以使用 go 指令引用该文件
package main
import (
"embed"
"fmt"
)
//go:embed data/file.txt
var content embed.FS
func main() {
text, _ := content.ReadFile("data/file.txt")
fmt.Println(string(text))
}
Run Code Online (Sandbox Code Playgroud)
无论程序在哪里执行,该程序都会成功运行。如果可以从多个不同位置(例如,从测试目录)调用该文件,这非常有用。