For now I used runtime.Caller(0)
in combination with path.Dir
and filepath.Abs
to get the path to the currently executed file and get the project root relative to it.
So lets say I've a folder structure like this:
$GOPATH/src/example.org/myproject
$GOPATH/src/example.org/myproject/main.go
$GOPATH/src/example.org/myproject/path
$GOPATH/src/example.org/myproject/path/loader.go
If I want my project root I call the loader.go which in turn gets its path with runtime.Caller(0)
and then goes up one folder to reach the project root.
The problem is when using go test -cover
the executed file is not in its normal place anymore but in a special sub directory for the testing and coverage analysis.runtime.Caller(0)
gives me the following:
example.org/myproject/path/_test/_obj_/loader.go
Running it through path.Dir
and filepath.Abs
will give me:
$GOPATH/src/example.org/myproject/path/example.org/myproject/path/_test/_obj_
When I go up from there I won't reach the project root but something totally different obviously. So my questions stands:
Is there any reliable way of getting the project root?
In order to get the root directory path, you can use _DIR_ or dirname(). echo dirname(__FILE__); Both the above syntaxes will return the same result.
Type “echo %SYSTEMROOT%" at the command prompt and press “Enter.” The result of this search is the root folder for Microsoft Windows.
At runtime node creates a registry of the full paths of all loaded files. The modules are loaded first, and thus at the top of this registry. By selecting the first element of the registry and returning the path before the 'node_modules' directory we are able to determine the root of the application.
Getwd functionis used to get the current working directory in Golang, the function returns the rooted path name and if the current directory can be reached via multiple paths, the function can return any one of them.
You can build it from the $GOPATH
env variable:
gp := os.Getenv("GOPATH")
ap := path.Join(gp, "src/example.org/myproject")
fmt.Println(ap)
That will yield the absolute path to your paroject dir:
/path/to/gopath/src/example.org/myproject
This obviously only works when GOPATH
is set. aka. on your dev machine. On production you need to supply directories via a config file.
See this answer. In case you are using go ~ 1.8, func Executable() (string, error)
is an option I stumbled over when I needed it. I tested briefly how it interacts with go test -cover
and it seems to work fine:
func Executable() (string, error)
Executable returns the path name for the executable that started the current process. There is no guarantee that the path is still pointing to the correct executable. If a symlink was used to start the process, depending on the operating system, the result might be the symlink or the path it pointed to. If a stable result is needed, path/filepath.EvalSymlinks might help.
package main
import (
"fmt"
"os"
"path"
)
func main() {
e, err := os.Executable()
if err != nil {
panic(err)
}
path := path.Dir(e)
fmt.Println(path)
}
The test:
binpath.go
:
package binpath
import (
"os"
"path"
)
func getBinPath() string {
e, err := os.Executable()
if err != nil {
panic(err)
}
path := path.Dir(e)
return path
}
binpath_test.go
:
package binpath
import (
"fmt"
"testing"
)
func TestGetBinPath(t *testing.T) {
fmt.Println(getBinPath())
}
Results in something like /tmp/go-build465775039/github.com/tworabbits/binpath/_test
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With