本人是新學(xué)go語言,文章僅供學(xué)習(xí)所用冰寻,如有錯(cuò)誤之處仲器,煩請(qǐng)指正煤率。
一、簡(jiǎn)介
go中支持的MySQL驅(qū)動(dòng)比較多乏冀,推薦最多的是https://github.com/go-sql-driver/mysql,支持database/sql標(biāo)準(zhǔn)蝶糯。
二、使用前的準(zhǔn)備
1.引用
需要引用兩個(gè)包
import "database/sql"
import _ "github.com/go-sql-driver/mysql"
備注:_是只引入包名(即只使用init函數(shù)注冊(cè)mysql數(shù)據(jù)庫驅(qū)動(dòng))而不直接使用保重定義的函數(shù)
2.連接數(shù)據(jù)庫
sql.Open() 打開一個(gè)由其數(shù)據(jù)庫驅(qū)動(dòng)程序名稱和驅(qū)動(dòng)程序特定的數(shù)據(jù)源名稱指定的數(shù)據(jù)庫辆沦,通常由至少一個(gè)數(shù)據(jù)庫名稱和連接信息組成昼捍。方法定義如下:
func Open(driverName, dataSourceName string) (*DB, error)
有兩個(gè)參數(shù):第一個(gè)參數(shù)driverName是注冊(cè)進(jìn)去的數(shù)據(jù)庫名稱识虚,第二個(gè)參數(shù)是數(shù)據(jù)庫連接和配置信息。格式如下:
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
db,err := sql.Open("mysql", "root:@tcp(localhost:3306)/default?charset=utf8")
if err != nil {
panic(err)
}
三妒茬、mysql基本操作(增刪改查)
db.Prepare()方法為以后的查詢或執(zhí)行創(chuàng)建一個(gè)準(zhǔn)備好的語句(用于增刪改),返回一個(gè)準(zhǔn)備完畢的執(zhí)行狀態(tài)stmt
func (db *DB) Prepare(query string) (*Stmt, error)
stmt.Exec()使用給定的參數(shù)執(zhí)行一個(gè)準(zhǔn)備好的語句担锤,并返回一個(gè)總結(jié)語句效果的Result結(jié)果集
func (s *Stmt) Exec(args ...interface{}) (Result, error)
1.增改查(操作都差不多,故放一塊)
db,err := sql.Open("mysql", "root:root@tcp(localhost:3306)/default?charset=utf8")
if err != nil {
panic(err)
}
//新增一條數(shù)據(jù)
stmt, err := db.Prepare(`INSERT user (uname, age, mobile) VALUES (?, ?, ?)`)
if err != nil {
panic(err)
}
defer stmt.Close() //延時(shí)關(guān)閉一個(gè)準(zhǔn)備好的資源
res, err := stmt.Exec("fightWang",28,"18888888888")
if err != nil {
panic(err)
}
//更新數(shù)據(jù)(修改id=5的數(shù)據(jù))
stmt, err = db.Prepare("update user set mobile=? where id=?")
if err != nil {
panic(err)
}
res, err = stmt.Exec("18899999999",5)
//刪除數(shù)據(jù)(刪除id=5的數(shù)據(jù))
stmt, err = db.Prepare("DELETE FROM user where id=?")
if err != nil {
panic(err)
}
res, err = stmt.Exec(5)
增刪改也可以直接使用db.Exec()方法(注意與stmt.Exec()的區(qū)別)
func (db *DB) Exec(query string, args ...interface{}) (Result, error)
2.查(多條)
與增刪改一樣乍钻,可以配合db.Prepare()使用stmt.Query()方法來查詢肛循,結(jié)果返回Rows結(jié)果集
func (s *Stmt) Query(args ...interface{}) (*Rows, error)
stmt, err := db.Prepare(`SELECT * FROM user WHERE mobile=?`)
if err != nil {
panic(err)
}
rows, err := stmt.Query("18888888888")
if err != nil {
panic(err)
}
查詢操作也可以直接使用db.Query()方法(注意與stmt.Query()的區(qū)別)
func (db *DB) Query(query string, args ...interface{}) (*Rows, error)
rows返回結(jié)果是多個(gè)結(jié)果行的集合,可以通過rows.Next()和rows.Scan()方法來獲取行內(nèi)數(shù)據(jù)
rows.Next()接下來準(zhǔn)備下一個(gè)結(jié)果行以便用Scan方法讀取团赁。它在成功時(shí)返回true育拨,如果沒有下一個(gè)結(jié)果行或在準(zhǔn)備過程中發(fā)生錯(cuò)誤,則返回false欢摄。
func (rs *Rows) Next() bool
rows.Close() 關(guān)閉行熬丧,防止進(jìn)一步枚舉。如果Next被調(diào)用并返回false怀挠,并且沒有其他結(jié)果集析蝴,則行自動(dòng)關(guān)閉,并且檢查Err的結(jié)果就足夠了绿淋。關(guān)閉是冪等的闷畸,不會(huì)影響Err的結(jié)果。故在調(diào)用的時(shí)候使用defer rows.Close()
是一個(gè)好習(xí)慣
func (rs *Rows) Close() error
rows.Scan()將當(dāng)前行中的列復(fù)制到dest指向的值中吞滞。dest中的值數(shù)量必須與行中的列數(shù)相同
func (rs *Rows) Scan(dest ...interface{}) error
rows, err := db.Query("SELECT * FROM user") //user表中共四個(gè)字段
if err != nil {
panic(err)
}
defer rows.Close()
uid, uname, age, mobile := 0,"",0,""
for rows.Next() {
err = rows.Scan(&uid,&uname,&age,&mobile) //要四個(gè)字段一一對(duì)齊
if err != nil {
panic(err)
}
fmt.Println(uid, uname, age, mobile)
}
3.查詢(單條查詢)
可以通過db.QueryRow()或者配合db.Prepare()和stmt.QueryRow()查詢單條結(jié)果佑菩。
db.QueryRow()執(zhí)行一個(gè)查詢,該查詢最多只返回一行裁赠。QueryRow總是返回一個(gè)非零值殿漠。錯(cuò)誤被推遲到行的掃描方法被調(diào)用(row.Scan())。
func (db *DB) QueryRow(query string, args ...interface{}) *Row
stmt.QueryRow()使用給定的參數(shù)執(zhí)行一個(gè)準(zhǔn)備好的查詢語句佩捞。如果在執(zhí)行語句期間發(fā)生錯(cuò)誤绞幌,則在返回的*行上調(diào)用Scan以返回該錯(cuò)誤,該行總是非零
func (s *Stmt) QueryRow(args ...interface{}) *Row
id := 123
var username string
err := db.QueryRow("SELECT username FROM users WHERE id=?", id).Scan(&username)
switch {
case err == sql.ErrNoRows: //當(dāng)QueryRow沒有返回行時(shí)一忱,Scan返回ErrNoRows莲蜘。在這種情況下,QueryRow會(huì)返回一個(gè)占位符* Row值帘营,該值將推遲發(fā)生此錯(cuò)誤直到掃描票渠。
log.Printf("No user with that ID.")
case err != nil:
log.Fatal(err)
default:
fmt.Printf("Username is %s\n", username)
}
四、mysql其他常用操作
1.獲取執(zhí)行插入行操作的主鍵id值
LastInsertId() (int64, error)
//新增一條數(shù)據(jù)
stmt, err := db.Prepare(`INSERT user (uname, age, mobile) VALUES (?, ?, ?)`)
if err != nil {
panic(err)
}
res, err := stmt.Exec("fightWang",28,"18888888888")
if err != nil {
panic(err)
}
uid, err := res.LastInsertId()
if err != nil {
panic(err)
}
fmt.Println(uid) //返回新插入行的主鍵
2.返回受到影響的行數(shù)(Insert | Update | Delete)
num, err := res.RowsAffected()
if err != nil {
panic(err)
}
fmt.Println(num) //返回新插入行的主鍵
3.獲取表的字段(列)名(僅用于多條查詢)
rows.Columns() 將返回列名稱組成的slice芬迄。如果行關(guān)閉庄新,或者行來自QueryRow并且存在延遲錯(cuò)誤,則列將返回錯(cuò)誤。
func (rs *Rows) Columns() ([]string, error)
stmt, err := db.Prepare("SELECT * FROM user")
if err != nil {
panic(err)
}
defer stmt.Close()
rows, err := stmt.Query()
if err != nil {
panic(err)
}
defer rows.Close()
columns, err := rows.Columns()
if err != nil {
panic(err)
}
fmt.Println(columns) //[id uname age mobile]