我刚开始在Go中开发Web应用程序。 我正在寻找将MySQL数据库集成到我的Web应用程序中的最佳方法。
我在考虑做这样的事情:
type Context struct {
Database *sql.DB
}
// Some database methods like Close() and Query() for Context struct here
在我的Web应用程序的主要功能中,我会有这样的事情:
db := sql.Open(...)
ctx := Context{db}
然后我会传递然后将我的Context
结构传递给需要数据库连接的各种处理程序。这是一个很好的设计决策,还是有更好的方法将SQL数据库集成到我的Web应用程序中?
答案 0 :(得分:1)
我通常做这样的事情:
package main
func main(){
db,err := sql.Open(...)
if err != nil {
log.Fatal(err)
}
defer db.Close()
http.HandleFunc("/feed", server.FeedHandler(db))
http.HandleFunc("/gui", server.GuiHandler(db))
...
log.Fatal(http.ListenAndServe(":8000", nil))
}
其中server
是一个单独的包,我在其中定义,实现和测试我的所有http处理程序。
这基本上是你想到的,但是跳过了将db包装在一个不必要的结构中的步骤。我会不建议将db作为全局变量。拥有全局依赖性将完全破坏以可靠的方式测试http处理程序的任何可能性。
依赖注入数据库,如上例所示,每次调用函数时都要花费两个额外的字符来输入,但它允许您使用go-sqlmock package轻松测试您的http处理程序,您肯定想要这样做随着您的网络应用程序的增长。
package server
func TestFeedHandler(t *testing.T){
mockdb, err := sqlmock.New()
if err != nil {
t.Errorf("An error '%s' was not expected when opening a stub database connection", err)
}
columns := []string{"id", "name"}
sqlmock.ExpectQuery("SELECT id,name from persons;").
WillReturnRows(sqlmock.NewRows(columns).
AddRow(1234, "bob")
handler := FeedHandler(mockdb)
// test that handler returns expected result
}