英文:
Golang & MySQL - Managing Connections
问题
我在处理使用MySQL的golang web应用程序中的连接时遇到了问题。
在我看过的教程中,数据库交互都是在主函数中处理的。
然而,在实际应用中,每个HTTP请求都会与数据库交互 - 我应该在哪里保留sql.Open()和defer sql.Close()?这是我的代码。
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"html/template"
"net/http"
)
var db *sql.DB
var pageTemplate = template.Must(template.ParseFiles("index.html"))
type Items []string
func main() {
db, err := sql.Open("mysql",
"username:passwordl@tcp(127.0.0.1:3306)/databasename")
checkErr(err)
defer db.Close()
_, err = db.Exec(
`
CREATE TABLE IF NOT EXISTS items (
item_id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
item TEXT
);
`)
checkErr(err)
http.HandleFunc("/", mainHandler)
http.ListenAndServe(":3000", nil)
}
func mainHandler(w http.ResponseWriter, r *http.Request) {
var item string
var items Items
stmt, err := db.Prepare("select item from items")
checkErr(err)
defer stmt.Close()
rows, err := stmt.Query()
checkErr(err)
defer rows.Close()
for rows.Next() {
err := rows.Scan(&item)
checkErr(err)
items = append(items, item)
}
if err = rows.Err(); err != nil {
checkErr(err)
}
pageTemplate.Execute(w, items)
}
func checkErr(err error) {
if err != nil {
fmt.Println(err)
}
}
我在以下代码行上遇到了运行时错误:
stmt, err := db.Prepare("select item from items")
可能是因为在main函数之外无法识别db。我应该在每个URL处理程序上使用sql.Open()吗?
如果问题不明确,我向你道歉。
英文:
I'm having trouble handling connections in a golang web app that uses MySQL.
In the tutorials I have seen the database interaction is all handled once, in the main function.
However, in the real world each http request will interact with the database - where should I keep sql.Open() and defer sql.Close()? Here is my code.
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"html/template"
"net/http"
)
var db *sql.DB
var pageTemplate = template.Must(template.ParseFiles("index.html"))
type Items []string
func main() {
db, err := sql.Open("mysql",
"username:passwordl@tcp(127.0.0.1:3306)/databasename")
checkErr(err)
defer db.Close()
_, err = db.Exec(
`
CREATE TABLE IF NOT EXISTS items (
item_id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
item TEXT
);
`)
checkErr(err)
http.HandleFunc("/", mainHandler)
http.ListenAndServe(":3000", nil)
}
func mainHandler(w http.ResponseWriter, r *http.Request) {
var item string
var items Items
stmt, err := db.Prepare("select item from items")
checkErr(err)
defer stmt.Close()
rows, err := stmt.Query()
checkErr(err)
defer rows.Close()
for rows.Next() {
err := rows.Scan(&item)
checkErr(err)
items = append(items, item)
}
if err = rows.Err(); err != nil {
checkErr(err)
}
pageTemplate.Execute(w, items)
}
func checkErr(err error) {
if err != nil {
fmt.Println(err)
}
}
I get a runtime error on the line:
stmt, err := db.Prepare("select item from items")
Persumably because the db isn't recognised outside of the main function. Should I instead have sql.Open() on each url Handler?
Apologies if the question is ambiguous.
答案1
得分: 4
问题是,你在主函数内部重新声明了db。
将以下代码进行更改:
db, err := sql.Open("mysql",
更改为:
var err error
db, err = sql.Open("mysql",
此外,考虑阅读有关在应用程序中进行数据库访问时的不同组织方法。这是一篇很好的文章:http://www.alexedwards.net/blog/organising-database-access
英文:
The problem is, you are redeclaring db inside your main function.
change:
db, err := sql.Open("mysql",
to:
var err error
db, err = sql.Open("mysql",
Also consider reading about diffrent organizing methods when it comes to db access in your app. This is a great read: http://www.alexedwards.net/blog/organising-database-access
答案2
得分: 2
在db, err := ...
语句中,操作符:=
将定义一个新变量并隐藏同名的全局变量。
英文:
In the
db, err := ...
statement the operator :=
will define an new variable and hidde the global one with the same name.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论