如何为 godotenv.Load() .env 文件使用动态位置?
How to use dynamic location for godotenv.Load() .env file?
问题
我正在用 Go 构建 REST API。 godotenv package 用于加载环境变量。 运行go run main.go
,项目运行如期API,环境变量已加载。
然而,当想要 运行 测试使用:go test ./...
- 运行s config/config_test.go
等 - 它会抛出以下错误:Error loading .env file
(在函数中指定)。
给定以下项目结构:
> app
> auth
> config
- config.go
- config_test.go
> migrations
> static
> vendor
- .env
- .gitignore
- docker-compose.yml
- go.mod
- go.sum
- main.go
- README.md
在config.go中,我使用以下函数加载数据库配置。
func GetConfig() *Config {
err := godotenv.Load(".env")
if err != nil {
log.Fatalf("Error loading .env file")
}
dbHost := os.Getenv("DB_HOST")
dbPort := os.Getenv("DB_PORT")
dbName := os.Getenv("DB_DATABASE")
dbUsername := os.Getenv("DB_USERNAME")
dbPassword := os.Getenv("DB_PASSWORD")
return &Config{
DB: &DBConfig{
Connection: "mysql",
Host: dbHost,
Port: dbPort,
Username: dbUsername,
Password: dbPassword,
Name: dbName,
Charset: "utf8",
},
}
}
我知道当从 root 运行ning 时它有效,因为 .env
驻留在 root 中。当 运行ning config/config_test.go
时,它会尝试在 /config/.env
中查找 .env
文件。如果我将行更改为:err := godotenv.Load(".env")
到 err := godotenv.Load("../.env")
,config_test.go 运行 成功,但来自 root 的 go run main.go
不会 运行 成功。
问题
如何从 config.go
中的 GetConfig()
函数动态加载 .env
位置,以便 go test ./...
和 go run main.go
都可以加载.env
?
编辑
我知道将 path string
参数传递给 GetConfig()
函数可以在我的应用程序中运行(我正在应用程序包中初始化此配置)。但是,我想在不同的目录中创建多个测试,并且不希望传递参数。还有其他方法可以实现吗?
根据@Inian 的建议,我实施了以下解决方案,也列在 godotenv package 的 Issues
选项卡上。
在 config.go 中,我为目录名称添加了一个常量(在我的例子中是 rest-api
)。我添加了一个 loadEnv
函数,试图根据项目名称和当前工作目录动态获取项目的根路径。
const projectDirName = "rest-api" // change to relevant project name
func loadEnv() {
projectName := regexp.MustCompile(`^(.*` + projectDirName + `)`)
currentWorkDirectory, _ := os.Getwd()
rootPath := projectName.Find([]byte(currentWorkDirectory))
err := godotenv.Load(string(rootPath) + `/.env`)
if err != nil {
log.Fatalf("Error loading .env file")
}
}
func GetConfig() *Config {
loadEnv()
dbHost := os.Getenv("DB_HOST")
dbPort := os.Getenv("DB_PORT")
dbName := os.Getenv("DB_DATABASE")
dbUsername := os.Getenv("DB_USERNAME")
dbPassword := os.Getenv("DB_PASSWORD")
return &Config{
DB: &DBConfig{
Connection: "mysql",
Host: dbHost,
Port: dbPort,
Username: dbUsername,
Password: dbPassword,
Name: dbName,
Charset: "utf8",
},
}
}
问题
我正在用 Go 构建 REST API。 godotenv package 用于加载环境变量。 运行go run main.go
,项目运行如期API,环境变量已加载。
然而,当想要 运行 测试使用:go test ./...
- 运行s config/config_test.go
等 - 它会抛出以下错误:Error loading .env file
(在函数中指定)。
给定以下项目结构:
> app
> auth
> config
- config.go
- config_test.go
> migrations
> static
> vendor
- .env
- .gitignore
- docker-compose.yml
- go.mod
- go.sum
- main.go
- README.md
在config.go中,我使用以下函数加载数据库配置。
func GetConfig() *Config {
err := godotenv.Load(".env")
if err != nil {
log.Fatalf("Error loading .env file")
}
dbHost := os.Getenv("DB_HOST")
dbPort := os.Getenv("DB_PORT")
dbName := os.Getenv("DB_DATABASE")
dbUsername := os.Getenv("DB_USERNAME")
dbPassword := os.Getenv("DB_PASSWORD")
return &Config{
DB: &DBConfig{
Connection: "mysql",
Host: dbHost,
Port: dbPort,
Username: dbUsername,
Password: dbPassword,
Name: dbName,
Charset: "utf8",
},
}
}
我知道当从 root 运行ning 时它有效,因为 .env
驻留在 root 中。当 运行ning config/config_test.go
时,它会尝试在 /config/.env
中查找 .env
文件。如果我将行更改为:err := godotenv.Load(".env")
到 err := godotenv.Load("../.env")
,config_test.go 运行 成功,但来自 root 的 go run main.go
不会 运行 成功。
问题
如何从 config.go
中的 GetConfig()
函数动态加载 .env
位置,以便 go test ./...
和 go run main.go
都可以加载.env
?
编辑
我知道将 path string
参数传递给 GetConfig()
函数可以在我的应用程序中运行(我正在应用程序包中初始化此配置)。但是,我想在不同的目录中创建多个测试,并且不希望传递参数。还有其他方法可以实现吗?
根据@Inian 的建议,我实施了以下解决方案,也列在 godotenv package 的 Issues
选项卡上。
在 config.go 中,我为目录名称添加了一个常量(在我的例子中是 rest-api
)。我添加了一个 loadEnv
函数,试图根据项目名称和当前工作目录动态获取项目的根路径。
const projectDirName = "rest-api" // change to relevant project name
func loadEnv() {
projectName := regexp.MustCompile(`^(.*` + projectDirName + `)`)
currentWorkDirectory, _ := os.Getwd()
rootPath := projectName.Find([]byte(currentWorkDirectory))
err := godotenv.Load(string(rootPath) + `/.env`)
if err != nil {
log.Fatalf("Error loading .env file")
}
}
func GetConfig() *Config {
loadEnv()
dbHost := os.Getenv("DB_HOST")
dbPort := os.Getenv("DB_PORT")
dbName := os.Getenv("DB_DATABASE")
dbUsername := os.Getenv("DB_USERNAME")
dbPassword := os.Getenv("DB_PASSWORD")
return &Config{
DB: &DBConfig{
Connection: "mysql",
Host: dbHost,
Port: dbPort,
Username: dbUsername,
Password: dbPassword,
Name: dbName,
Charset: "utf8",
},
}
}