資料庫
標準庫 database/sql
中已經封裝好資料庫操作的介面和規範,如連線池管理、資料繫結、事務處理等。但對具體資料庫
型別需要第三方驅動,如果mysql sqlite
等。
載入
var db *sql.DB //宣告資料庫操作變數
func initDB(){} //初始化操作函式,連線池管理等
func main() {
initDB() //呼叫函式進行初始化
}
建表函式
func createTables() {
createArticlesSQL := `CREATE TABLE IF NOT EXISTS articles(
id bigint(20) PRIMARY KEY AUTO_INCREMENT NOT NULL,
title varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
body longtext COLLATE utf8mb4_unicode_ci ); `
_, err := db.Exec(createArticlesSQL)
checkError(err) }
把建表的sql語句賦給createArticlesSQL
變數,然後執行db.Exec()
。放在main中執行,判斷沒有就新建。這張表三個欄位:id 是bigint型別作為主鍵並自增,titel為varchar型別 設定collate,body為longtext型別。
sql.Result
db.Exec() 執行一個不帶返回結果集的命令。類似用在inser、update、delete上。
func (db *DB) Exec(query string, args …interface{}) (Result, error)
Result定義:
type Result interface {
LastInsertId() (int64, error) // 使用 INSERT 向資料插入記錄,資料表有自增 id 時,該函式有返回值
RowsAffected() (int64, error) // 表示影響的資料錶行數
}
儲存資料到資料庫
博文資料需要儲存到資料庫中,新增一個函式,然後在處理器中呼叫:
在articlesStoreHandler
中:
lastInsertID, err := saveArticleToDB(title, body)
if lastInsertID > 0 {
fmt.Fprint(w, "插入成功,ID 為"+strconv.FormatInt(lastInsertID, 10))
} else {
checkError(err)
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprint(w, "500 伺服器內部錯誤")
}
重點講saveArticlesToDB函式:
func saveArticleToDB(title string, body string) (int64, error) {}
處理步驟是先進行db.Perpare(),取得一個 *sql.Stmt,defer stmt.Close(),再執行stmt.Exec(title,body)插入,返回一個sql.Result,如果插入成功的話,結果集有返回的自增 ID。這裡一個插入,訪問資料庫2次。
顯示文章
二個步驟:讀取資料,渲染模版。
在handlerShow中,先獲取請求URL的id:
vars := mux.Vars(r)
id := vars["id"]
把sql查詢語句賦個query,呼叫db.QueryRow()
:
err := db.QueryRow(query, id).Scan(&article.ID, &article.Title, &article.Body)
QueryRow() 會返回一個 sql.Row struct,Scan()將查詢結果賦值到Article結構的變數article中。
Scan() 發現沒有返回資料的話,會返回 sql.ErrNoRows 型別的錯誤。
讀取成功後,用template.ParseFiles()
載入模版進行渲染。
show.gohtml:
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{ .Title }} —— 我的技術部落格</title>
<style type="text/css">.error {color: red;}</style>
</head>
<body>
<p>ID: {{ .ID }}</p>
<p>標題: {{ .Title }}</p>
<p>內容:{{ .Body }}</p>
</body>
</html>
本作品採用《CC 協議》,轉載必須註明作者和本文連結