我使用io/ioutil
读取一个小文本文件:
fileBytes, err := ioutil.ReadFile("/absolute/path/to/file.txt")
这很好用,但是这不是完全可移植的。在我的例子中,我想打开的文件在我的GOPATH中,例如:
/Users/matt/Dev/go/src/github.com/mholt/mypackage/data/file.txt
由于data
文件夹就在源代码旁边,所以我只想指定相对路径:
data/file.txt
但是我得到了这个错误:
死机:打开数据/文件. txt:无此文件或目录
如何使用相对路径打开文件,特别是当它们和我的Go语言代码放在一起的时候?
- (**注意我的问题是关于相对于GOPATH打开文件的。*在Go语言中使用任何相对路径打开文件都很简单,只要给出相对路径而不是绝对路径即可;文件相对于编译后的二进制文件的工作目录打开。在我的例子中,我希望相对于二进制文件编译的位置打开文件。事后看来,这是一个糟糕的设计决策。)
5条答案
按热度按时间fivyi3re1#
嗯......
path/filepath
软件包有Abs()
,它满足了我的需求(到目前为止),尽管有点不方便:然后我使用
absPath
加载文件,它工作正常。注意,在我的例子中,数据文件在一个独立于
main
包的包中,如果它们都在同一个包中,我会删除前面的../mypackage/
,因为这个路径显然是相对的,不同的程序将有不同的结构,需要相应地调整。如果有更好的方法来使用外部资源并保持程序的可移植性,请随意给出另一个答案。
jm2pwxwz2#
这看起来工作得很好:
rqenqsqc3#
我编写gobundle就是为了解决这个问题。它从数据文件中生成Go语言源代码,然后编译成二进制文件。然后可以通过一个类似于VFS的层访问文件数据。它是完全可移植的,支持添加整个文件树、压缩等。
缺点是您需要一个中间步骤来从源数据构建Go文件,我通常使用make来实现这一点。
下面是如何遍历bundle中的所有文件,阅读字节:
您可以在我的GeoIP包中看到一个使用它的真实的示例。
Makefile
生成代码,geoip.go
使用VFS。8nuwlpux4#
从Go语言1.16开始,可以使用embed包,这样就可以把文件嵌入到正在运行的Go语言程序中。
给定文件结构:
可以使用go指令引用该文件
无论程序在何处执行,此程序都将成功运行。这在可以从多个不同位置调用文件的情况下很有用,例如,从测试目录。
ajsxfq5m5#
我认为Alec托马斯已经提供了答案,但根据我的经验,这并不是万无一失的。我在将资源编译成二进制文件时遇到的一个问题是,根据资源的大小,编译可能需要大量内存。如果资源很小,那么可能就没什么可担心的。在我的特定场景中,一个1 MB的字体文件导致编译需要大约1GB的内存。这是一个问题,因为我希望它可以在树莓派上获得。这是Go语言1.0;在Go语言1.1中可能有所改进。
因此,在这种特殊情况下,我选择只使用
go/build
包根据导入路径查找程序的源目录。当然,这要求您的目标设置了GOPATH
,并且源文件可用。因此,它不是在所有情况下都是理想的解决方案。