如何为包含DB conn之类的应用程序包设置全局配置?

时间:2017-11-05 03:50:51

标签: go

到目前为止,我已将应用程序分为两个包 - mainapp

在我的main()我启动服务器:

func main() {
    router := app.CreateRouter(app.Routes())
    log.Fatal(http.ListenAndServe(":8080", router))
}

在应用中,我有一个Config结构,其方法为connectToDB

type Config struct {
    DB *sql.DB
}

func (c *Config) connectToDB() {
    connectionString := fmt.Sprintf("user=%s password=%s dbname=%s sslmode=disable", os.Getenv("DB_USERNAME"), os.Getenv("DB_PASSWORD"), os.Getenv("DB_NAME"))
    var err error
    c.DB, err = sql.Open("postgres", connectionString)
    if err != nil {
        log.Fatal(err)
    }
}

func init() {
    c := Config{}
    c.connectToDB()
}

但是,我有各种处理程序,如果我想使用Config.DB,我该怎么做?

例如,在app.UserIndex中,如何进入Config.DB

func UserIndex(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
    fmt.Fprint(w, "test!\n")
}

现在,我能做的一件事就是设置一个全局变量,例如

var c Config

然后,我可以在包app中的任何位置访问c.DB。然而,这感觉很糟糕。

2 个答案:

答案 0 :(得分:1)

你可以创建一个var ( App struct { DB *sql.DB Timeout time.Duration ... } ) 变量来保存配置和其他一些有用的设置,例如Http超时

iframe

然后在这个结构上制作方法。这种方式将在应用程序实例中封装。

答案 1 :(得分:1)

如果你想避免使用全局变量,请使用处理程序结构而不是纯函数:

type UserIndex struct {
    cfg Config
}

func (u UserIndex) ServeHTTP(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
    fmt.Fprint(w, "test!\n")
}

设置路线时,请使用UserIndex{c}.ServeHTTP代替UserIndex

核心库http包因此而区分Handler类型和HandlerFunc。您似乎正在使用github.com/julienschmidt/httprouter,它没有做出这种区分,并且没有提供与其interface类型匹配的httprouter.Handle,但您仍然可以使用某种方法在一个结构上,以满足该类型。