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