如何获取相对于导入包路径的文件路径?

huangapple go评论87阅读模式
英文:

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)
  // ...
}

huangapple
  • 本文由 发表于 2015年7月8日 15:19:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/31285963.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定