godotenv
godotenv copied to clipboard
Load() does not use root
When I use godotenv.Load() in a file located in root (i.e. "main_test.go") it works perfectly and it finds the .env file.
However, when I use the same command in a file from a different folder (i.e. "controller/controller_test.go") it can not find the file. As a quick fix godotenv.Load("../.env") works.
Is this intended?
Just to elaborate: the path in workaround godotenv.Load("../.env")
is the relative path to .env
file w.r.t the test file in which you try to load the variables.
Thanks for the clarification. Is there a way to change this behaviour? Like LoadFromRoot
method or a parameter?
../.env
This works for whne you do go test
... but if you want to run it normally again go run
it will fail. Is there a clean way to do this?
I place my env files at the same dir as my go.mod. As every Go project must have a go.mod, I could implement like this. The envFile expects something like ".env" or ".env.test", etc.
// Load loads the environment variables from the .env file.
func Load(envFile string) {
err := godotenv.Load(dir(envFile))
if err != nil {
panic(fmt.Errorf("Error loading .env file: %w", err))
}
}
// dir returns the absolute path of the given environment file (envFile) in the Go module's
// root directory. It searches for the 'go.mod' file from the current working directory upwards
// and appends the envFile to the directory containing 'go.mod'.
// It panics if it fails to find the 'go.mod' file.
func dir(envFile string) string {
currentDir, err := os.Getwd()
if err != nil {
panic(err)
}
for {
goModPath := filepath.Join(currentDir, "go.mod")
if _, err := os.Stat(goModPath); err == nil {
break
}
parent := filepath.Dir(currentDir)
if parent == currentDir {
panic(fmt.Errorf("go.mod not found"))
}
currentDir = parent
}
return filepath.Join(currentDir, envFile)
}