这是完美的工作和数据库连接,没有问题。但我不想硬编码我的值在函数中,因此使用了env文件。但使用os.getenv并没有连接到数据库。
package main
import (
"database/sql"
"fmt"
_ "github.com/lib/pq"
)
const (
host = "localhost"
port = 5432
user = "bond"
password = "password"
dbname = "bookstore"
)
func main() {
psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+
"password=%s dbname=%s sslmode=disable",
host, port, user, password, dbname)
db, err := sql.Open("postgres", psqlInfo)
if err != nil {
panic(err)
}
defer db.Close()
err = db.Ping()
if err != nil {
panic(err)
}
fmt.Println("You connected to your database.")
}
字符串
下面的代码给出错误-panic: pq: password authentication failed for user "bond"
var (
host = "localhost"
port = 5432
user = "bond"
password = os.Getenv("DATABASE_PWD")
dbname = "bookstore"
)
型
为什么会发生这种情况?
2条答案
按热度按时间ilmyapht1#
你正在做类似这样的事情(playground):
字符串
这将不起作用,因为变量在
init
运行之前被初始化;这是根据规范:一个没有导入的包的初始化方法是将初始值赋给它的所有包级变量,然后按照它们在源代码中出现的顺序调用所有init函数,可能是在多个文件中,就像提交给编译器一样。如果一个包有导入,导入的包在初始化包本身之前被初始化。
因此,
password
的值是在运行godotenv.Load()
之前设置的(这意味着密码将是您启动应用程序时环境中的任何值-可能为空)。你可以通过在运行
godotenv.Load()
之后加载环境变量来修复这个问题。我建议在main
中这样做,这样你就可以处理任何错误(godotenv.Load()
可能会失败!)。请参阅包库中的示例。注意事项:这就是为什么包含minimal, reproducible, example很重要。在创建这样的示例时,您可能已经注意到
password
是空的,并且问题与database/sql
完全无关。如果没有比问题中提供的更多信息,则无法回答问题。92vpleto2#
为什么您的解决方案不能按预期工作
我想你误解了os.getEnv()函数的作用,你的操作系统有一个叫做环境变量的东西,这就是你在这里要得到的。
您的程式码会传回空字串,因为它未设定为环境变量。
您可以查看以下位置,了解有关此函数及其工作原理的更多信息:
你想做什么
现在,请允许我解释一下您实际要做的事情,您希望从文件中获取这些变量,因此您需要:
你可以通过两种方式来做到这一点。
第一个解决方案(自己动手)
首先打开文件并将其内容传递给扫描仪,然后遍历每一行,并使用“=”字符(Env格式)将该行一分为二,最后将其键/值存储在类似于Map(或任何您想要/需要的格式)的东西中。
第二个解决方案(用于惰性开发或复杂项目)
第二,如果您不想做所有这些,只需使用配置库或解析器来完成。
下面是使用Viper执行此操作的链接:Load config from file & environment variables in Golang with Viper