我们有一个程序,人们可以在他们的机器上编译。它有一个HTTP接口,但也可以通过命令行调用。加载需要的文件,相对于绝对路径
为了给HTTP客户端提供漂亮的错误页面,我们希望提供错误页面。我们使用go html/template
软件包,使用了非常简单的解决方案。
因此,为了使程序找到模板,我们目前正在做的事:
func init() {
prefStr := "path/to/http/tmpl"
pathPrefix,err := filepath.Abs(prefStr)
if err != nil {
log.Warn("Template path %s is not available!", prefStr)
}
pathPrefix + "/err.html"
}
现在调试应用程序时,这通常效果很好 - 我们是在包的根目录下,这样filepath.Abs()
正确解析,像这样: $GOPATH/github.com/user/repo/path/to/http/tmpl
(正确扩展$GOPATH
)
但是,当我们通过命令行通过可执行文件调用应用程序时,这是行不通的。命令行当然可以从文件系统的任何地方调用,以方便例如提供当前目录中的文件作为参数。
简而言之,运行/some/other/path/on/fs/our-executable filename.txt
导致上述init()
函数因目录错误拼接而中断:它需要/some/other/path/on/fs/
来创建绝对路径,这是错误的。因此,它与 panic: open /some/other/path/on/fs/path/to/http/tmpl/err.html: no such file or directory
我已经搜查,到目前为止,只发现这个崩溃: How can I open files using relative paths in Go?
但这正是并不适用于我们。 另一种解决方案提出捆绑编译的go资源,但这看起来很奇怪,因为错误页面是html文本。
我们也试过 https://stackoverflow.com/a/31464648/169252
,但它具有相同的效果。
我们如何确保路径始终正确解析?这似乎是一件不应该太难完成的事情,但我们目前还没有成功。
编辑:这不是问题How can I open files using relative paths in Go?的确切副本。正如我在问题文本中已经提到的那样,我已经自己查阅了它。它建议使用filepath.Abs()
。但正如我的问题所阐明的那样,对我们来说这不起作用,就像我们的可执行文件被从不同的地方调用一样,filepath.Abs()
不会返回相同的值,因此对我们不起作用。
'path/to/http/tmpl'是绝对路径吗?这意味着它从文件系统的根目录开始。例子'/ home/faboolous/abc/defg/tmpl' –
@ SamuelToh不,它不是绝对路径,否则它不能移植。这是从回购的根源的相对路径。 – faboolous
使用[go-bindata](https://github.com/jteeuwen/go-bindata)将模板编译为go二进制文件 – Mark