英文:
How to get filepath relative to imported package's path?
问题
问题是我无法访问相对于实际使用的包路径的文件。让我们来看一个例子。我有以下结构:
~/go/src/github.com/user/dbms
data/
database.db
dbms.go
~/projects/myproj/bin
main.go
dbms.go:
package dbms
import (
"os"
"fmt"
"path/filepath"
)
type dbms struct {
filepath string
}
func New() *dbms {
return &dbms{filepath: "./data/database.db"}
}
func (d *dbms) Run() {
fmt.Println(filepath.Abs(d.Path))
// 输出: /home/timur/projects/myproj/bin/data
// 我需要的是: /home/timur/go/src/github.com/user/dbms/data
file, err := os.OpenFile(d.filepath, os.O_RDWR, 0666)
// 错误
}
main.go:
package main
import (
"github.com/user/dbms"
)
func main() {
db := dbms.New()
db.Run()
}
如你所见,dbms.Path
解析的是相对于入口点的路径,而不是包本身的路径。我做错了什么?
英文:
The problem is I can't reach the file relative to the package path where it is actual used. Let's consider the example. I have the following structure:
~/go/src/github.com/user/dbms
data/
database.db
dbms.go
~/projects/myproj/bin
main.go
dbms.go:
package dbms
import (
"os"
"fmt"
"path/filepath"
)
type dbms struct {
filepath string
}
func New() *dbms {
return &dbms{filepath: "./data/database.db"}
}
func (d *dbms) Run() {
fmt.Println(filepath.Abs(d.Path))
// output: /home/timur/projects/myproj/bin/data
// I need: /home/timur/go/src/github.com/user/dbms/data
file, err := os.OpenFile(d.filepath, os.O_RDWR, 0666)
// error
}
main.go:
package main
import (
"github.com/user/dbms"
)
func main() {
db := dbms.New()
db.Run()
}
As you can see dbms.Path
resolves path relative to the entry point and not package itself. What do I wrong?
答案1
得分: 3
问题在于你的数据库文件不会成为编译后的二进制文件的一部分。似乎你期望在运行代码时,它会与二进制文件一起打包。
我认为你应该重新考虑你的方法。你的源代码将被编译成一个静态二进制文件来运行,但该二进制文件不会包含你的数据库文件。如果你试图可靠地猜测正确的路径,你将会遇到麻烦。
我建议将数据库文件的路径放入配置参数中,可以是一个在运行时必须位于当前工作目录中的配置文件,或者作为一个环境变量。然后,将数据库文件从包目录中移出,因为它在那里对你没有帮助。
至于在运行时最初获取文件,你可以添加一个设置函数来适当地创建你的数据库。或者,如果你期望数据库中有一些预加载的数据,可以将其与最终的二进制文件和配置文件一起打包。
希望对你有所帮助!
英文:
The issue is that your database file will not be a part of the compiled binary. It seems you are expecting it to be packaged with your binary when you run your code.
I think you should reconsider your approach. Your source code will be compiled into a static binary to be ran, but that binary will not include your database file. You are going to have a bad time trying to guess the correct path reliably.
I would move the path to your database file into a configuration param, either in a config file that is required to be in the current working directory at runtime, or as an environment variable. Then, pull the database file out of the package directory, since it won't be helping you by being there.
As far as getting the file initially at runtime, you could just add a setup function that will scaffold your database as appropriate. Or, if you are expecting some preloaded data in the database, just ship it in a package with the final binary and config file.
Hope that helps!
答案2
得分: 1
感谢@BravadaZadada提出的解决方案:
~/go/src/github.com/user/dbms
data/
database.db
dbms.go
~/projects/myproj/bin
main.go
dbms.go
package dbms
import (
"os"
"fmt"
"path/filepath"
)
type dbms struct {
filepath string
}
func New() *dbms {
// 在这里解决!
pck, err := build.Import("github.com/user/dbms", "", build.FindOnly);
return &dbms{filepath: filepath.Join(pck.Dir, "data/database.db")}
}
func (d *dbms) Run() {
fmt.Println(filepath.Abs(d.filepath))
// 输出: /home/timur/go/src/github.com/user/dbms/data
file, err := os.OpenFile(d.filepath, os.O_RDWR, 0666)
// ...
}
英文:
Thank to @BravadaZadada who suggested this solution:
~/go/src/github.com/user/dbms
data/
database.db
dbms.go
~/projects/myproj/bin
main.go
dbms.go
package dbms
import (
"os"
"fmt"
"path/filepath"
)
type dbms struct {
filepath string
}
func New() *dbms {
// Solution here!
pck, err := build.Import("github.com/user/dbms", "", build.FindOnly);
return &dbms{filepath: filepath.Join(pck.Dir, "data/database.db")}
}
func (d *dbms) Run() {
fmt.Println(filepath.Abs(d.filepath))
// output: /home/timur/go/src/github.com/user/dbms/data
file, err := os.OpenFile(d.filepath, os.O_RDWR, 0666)
// ...
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论