到目前为止,我已将应用程序分为两个包 - main
和app
在我的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。然而,这感觉很糟糕。
答案 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
,但您仍然可以使用某种方法在一个结构上,以满足该类型。