我們使用 https://github.com/Go-SQL-Driver/MySQL 作為Go連接MySQL的驅(qū)動(dòng)朵耕,進(jìn)行數(shù)據(jù)庫操作練習(xí)低飒。
(1)導(dǎo)入數(shù)據(jù)庫驅(qū)動(dòng)
import (
_"github.com/Go-SQL-Driver/MySQL"
)
這里使用 _ 的意思是引入后面的包名而不直接使用這個(gè)包中定義的函數(shù)围橡,變量等資源底燎。若出現(xiàn)無法導(dǎo)入的情況,我們可以使用以下方式解決(以 window系統(tǒng)為例)
windows+R 打開cmd衰猛,
輸入go get github.com/vmihailenco/redis ,
回車之后會(huì)自動(dòng)下載項(xiàng)目到GOPATH中的src目錄下,然后刷新IDE刹孔。
(2)數(shù)據(jù)庫連接
使用 sql.Open 用來打開一個(gè)注冊(cè)過的數(shù)據(jù)庫驅(qū)動(dòng)啡省,這里有幾種連接方式,如下所示髓霞,一般我們選用第二種方式
user@unix(/path/to/socket)/dbname?charset=utf8
user:password@tcp(localhost:3306)/dbname?charset=utf8
user:password@/dbname
user:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname
(3)增刪改查操作
package main
import (
"database/sql"
"fmt"
_"github.com/Go-SQL-Driver/MySQL"
)
const(
DBHostsIp = "localhost:3306"
DBUserName = "root"
DBPassWord = "123456"
DBName = "localmysql"
)
func main(){
//連接至數(shù)據(jù)庫
db,err := sql.Open("mysql", DBUserName+":"+DBPassWord+"@tcp("+DBHostsIp+")/"+DBName)
CheckErr(err)
insert(db)
//關(guān)閉數(shù)據(jù)庫連接
db.Close()
}
//插入demo
func insert(db *sql.DB) {
//準(zhǔn)備插入操作
stmt,err := db.Prepare("INSERT user (user_name,user_age,user_sex) values (?,?,?)")
CheckErr(err)
//執(zhí)行插入操作
res,err := stmt.Exec("limao",26,2)
CheckErr(err)
//返回最近的自增主鍵id
id,err := res.LastInsertId()
fmt.Println("LastInsertId: ",id)
}
//查詢demo
func query(db *sql.DB) {
//rows:返回查詢操作的結(jié)果集
rows,err := db.Query("SELECT * FROM user")
CheckErr(err)
//第一步:接收在數(shù)據(jù)庫表查詢到的字段名卦睹,返回的是一個(gè)string數(shù)組切片
columns, _ := rows.Columns() // columns: [user_id user_name user_age user_sex]
//根據(jù)string數(shù)組切片的長度構(gòu)造scanArgs、values兩個(gè)數(shù)組方库,scanArgs的每個(gè)值指向values相應(yīng)值的地址
scanArgs := make([]interface{}, len(columns))
values := make([]interface{}, len(columns))
for i := range values {
scanArgs[i] = &values[i]
}
for rows.Next() {
//將查詢到的字段名的地址復(fù)制到scanArgs數(shù)組中
err = rows.Scan(scanArgs...)
CheckErr(err)
//將行數(shù)據(jù)保存到record字典
record := make(map[string]string)
for i, col := range values {
if col != nil {
//字段名 = 字段信息
record[columns[i]] = string(col.([]byte))
}
}
fmt.Println(record)
}
}
//更新demo
func update(db *sql.DB) {
//準(zhǔn)備更新操作
stmt1,err := db.Prepare("UPDATE user SET user_age=?,user_sex=? WHERE user_id=?")
CheckErr(err)
//執(zhí)行更新操作
res1, err := stmt1.Exec(21, 2, 1)
CheckErr(err)
//查詢更新多少條信息
num, err := res1.RowsAffected()
CheckErr(err)
fmt.Println(num)
}
//刪除demo
func remove(db *sql.DB) {
//準(zhǔn)備刪除操作
stmt, err := db.Prepare(`DELETE FROM user WHERE user_id=?`)
CheckErr(err)
//執(zhí)行刪除操作
res, err := stmt.Exec(1)
CheckErr(err)
//查詢刪除多少條信息
num, err := res.RowsAffected()
CheckErr(err)
fmt.Println(num)
}
//檢查錯(cuò)誤信息
func CheckErr(err error) {
if err != nil {
panic(err)
}
}
總結(jié):
db.Prepare()函數(shù)用來返回準(zhǔn)備要執(zhí)行的sql操作结序,然后返回準(zhǔn)備完畢的執(zhí)行狀態(tài)。
db.Query()函數(shù)用來直接執(zhí)行Sql返回Rows結(jié)果纵潦。
stmt.Exec()函數(shù)用來執(zhí)行stmt準(zhǔn)備好的SQL語句徐鹤。
我們可以看到我們傳入的參數(shù)都是=?對(duì)應(yīng)的數(shù)據(jù),這樣做的方式可以一定程度上防止SQL注入邀层。