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

时间:2015-07-08 07:19:36

标签: go relative-path filepath

问题是我无法相对于实际使用的包路径到达文件。让我们考虑一下这个例子。我有以下结构:

~/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()
}

正如您所看到的,dbms.Path解析了相对于入口点的路径,而不是自行打包。我错了什么?

2 个答案:

答案 0 :(得分:3)

问题是您的数据库文件不是已编译二进制文件的一部分。在运行代码时,您似乎希望将它与二进制文件一起打包。

我认为你应该重新考虑你的方法。您的源代码将被编译为要运行的静态二进制文件,但该二进制文件将不包含您的数据库文件。你将不得不可靠地猜测正确的路径。

我会将数据库文件的路径移动到配置参数中,或者在运行时需要在当前工作目录中的配置文件中,或者作为环境变量。然后,将数据库文件从包目录中拉出来,因为它不会帮助你。

至于最初在运行时获取文件,您可以添加一个设置函数,该函数将根据需要构建数据库。或者,如果您希望数据库中有一些预加载的数据,只需将其发送到包含最终二进制文件和配置文件的包中。

希望有所帮助!

答案 1 :(得分: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 {
  // 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)
  // ...
}