2016-01-25 44 views
0

我在使用MySQL的golang web應用程序中處理連接時遇到了問題。Golang&MySQL - 管理連接

在教程中,我看到數據庫交互全部處理一次,在主函數中。然而,在現實世界中,每個http請求都會與數據庫交互 - 我應該在哪裏保存sql.Open()並推遲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:[email protected](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") 

Persumably因爲DB是不是主要的功能之外認可。我應該改爲在每個url處理程序上使用sql.Open()嗎?

道歉,如果問題不明確。

+1

sql.open是真的打開連接池。生成的db對象是線程安全的,可以被你的http處理器併發使用。你通常只會在退出應用程序之前調用db.Close() –

回答

4

問題是,你在你的主函數中重新聲明db。

變化:

db, err := sql.Open("mysql", 

到:

var err error 
db, err = sql.Open("mysql", 

也可以考慮閱讀不同勢的組織方法,當涉及到數據庫中你的應用程序的訪問。這是一個偉大的閱讀:http://www.alexedwards.net/blog/organising-database-access

+0

啊哈!非常感謝您的閱讀材料。非常感謝。 –

2

db, err := ... 

聲明運營商:=將定義一個新的變量和hidde全球一個具有相同的名稱。