使用env文件时Golang数据库/SQL无法连接

4dbbbstv  于 12个月前  发布在  Go
关注(0)|答案(2)|浏览(120)

这是完美的工作和数据库连接,没有问题。但我不想硬编码我的值在函数中,因此使用了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"
)


为什么会发生这种情况?

ilmyapht

ilmyapht1#

你正在做类似这样的事情(playground):

var (
    env      = make(map[string]string) // Simulated environoment
    password = env["DATABASE_PWD"]
)

func init() {
    // Simulate loading .env file (godotenv.Load())
    env["DATABASE_PWD"] = "foo"
}

func main() {
    fmt.Println(password) // Outputs a blank line
    fmt.Println(env["DATABASE_PWD"]) // Outputs "foo"
}

字符串
这将不起作用,因为变量在init运行之前被初始化;这是根据规范:
一个没有导入的包的初始化方法是将初始值赋给它的所有包级变量,然后按照它们在源代码中出现的顺序调用所有init函数,可能是在多个文件中,就像提交给编译器一样。如果一个包有导入,导入的包在初始化包本身之前被初始化。
因此,password的值是在运行godotenv.Load()之前设置的(这意味着密码将是您启动应用程序时环境中的任何值-可能为空)。
你可以通过在运行godotenv.Load()之后加载环境变量来修复这个问题。我建议在main中这样做,这样你就可以处理任何错误(godotenv.Load()可能会失败!)。请参阅包库中的示例。
注意事项:这就是为什么包含minimal, reproducible, example很重要。在创建这样的示例时,您可能已经注意到password是空的,并且问题与database/sql完全无关。如果没有比问题中提供的更多信息,则无法回答问题。

92vpleto

92vpleto2#

为什么您的解决方案不能按预期工作

我想你误解了os.getEnv()函数的作用,你的操作系统有一个叫做环境变量的东西,这就是你在这里要得到的。
您的程式码会传回空字串,因为它未设定为环境变量。
您可以查看以下位置,了解有关此函数及其工作原理的更多信息:

你想做什么

现在,请允许我解释一下您实际要做的事情,您希望从文件中获取这些变量,因此您需要:

  • 告诉程序它在哪里
  • 打开它
  • 解析它
  • 读取值

你可以通过两种方式来做到这一点。

第一个解决方案(自己动手)

首先打开文件并将其内容传递给扫描仪,然后遍历每一行,并使用“=”字符(Env格式)将该行一分为二,最后将其键/值存储在类似于Map(或任何您想要/需要的格式)的东西中。

第二个解决方案(用于惰性开发或复杂项目)

第二,如果您不想做所有这些,只需使用配置库或解析器来完成。
下面是使用Viper执行此操作的链接:Load config from file & environment variables in Golang with Viper

相关问题