原文作者:学生黄哲来源:简书
Go标准库中没有数据库驱动。参见http://golang.org/s/sqldrivers获取第三方驱动。这里选择了Go-MySQL-Driver这个实现。地址是:https://github.com/go-sql-driver/mysql/。安装:go get github.com/go-sql-driver/mysql官方database/sql包文档:https://studygolang.com/pkgdoc有关于MySQL基本操作可以去看我的另一篇简书:https://www.jianshu.com/p/2e01f4c6b626使用的数据库定义如下
函数原型func Open(driverName, dataSourceName string) (*DB, error)Open打开一个dirverName指定的数据库,dataSourceName指定数据源,一般包至少括数据库文件名和(可能的)连接信息。
1//第⼀步:打开数据库,格式是 ⽤户名:密码@/数据库名称?编码⽅式 2 db, err := sql.Open("mysql", "root:123@/mydb?charset=utf8") 3 if err != nil { 4 fmt.Println(err) 5 } 6 //关闭数据库 7 defer db.Close()函数原型func (db *DB) Query(query string, args ...interface{}) (*Rows, error)Query执行一次查询,返回多行结果(即Rows),一般用于执行select命令。参数args表示query中的占位参数。
1var id int 2 var name string 3 var price float64 4 //查询数据,指定字段名,返回sql.Rows结果集 5 rows, err := db.Query("select id,name,price from product") 6 if err != nil { 7 fmt.Println(err) 8 } 9 for rows.Next() { 10 rows.Scan(&id, &name, &price) 11 fmt.Println(id, name, price) 12 } 13 defer rows.Close()• rows.Next() 迭代查询数据.• rows.Scan() 读取每一行的值• rows.Close() 关闭查询
函数原型func (db *DB) QueryRow(query string, args ...interface{}) *RowQueryRow执行一次查询,并期望返回最多一行结果(即Row)。QueryRow总是返回非nil的值,直到返回值的Scan方法被调用时,才会返回被延迟的错误。
1//查询⼀⾏数据可以使用and(与)限定多个条件,或者使用or(或) 2 rows3 := db.QueryRow("SELECT id,name FROM product WHERE id = ? or price like ?", 1,1.11) 3 // rows3 := db.QueryRow("select id,name from product where id = 1") 4 rows3.Scan(&id, &name) 5 fmt.Println(id, name) 6函数原型func (s *Stmt) Exec(args ...interface{}) (Result, error)Exec使用提供的参数执行准备好的命令状态,返回Result类型的该状态执行结果的总结。
1//插⼊⼀⾏数据 2 ret, _ := db.Exec("insert into product(id,name,price) values(15,'dog',30)") 3 //LastInsertId返回一个数据库生成的回应命令的整数。 4 //返回插入的ID 5 insID, _ := ret.LastInsertId() 6 fmt.Println(insID) 7• ret.LastInsertId()插入的ID• ret.RowsAffected()受影响的行数
函数原型func (db *DB) Prepare(query string) (*Stmt, error)Prepare创建一个准备好的状态用于之后的查询和命令。返回值可以同时执行多个查询和命令。
1 //预处理 2 stmt, _ := db.Prepare("select id,name from product where id=? or name=?") 3 //查找id为3或者name为000的人 4 row4, _ := stmt.Query(3, "000") 5 //注意这⾥需要Next()下,不然下⾯取不到值 6 for row4.Next() { 7 row4.Scan(&id, &name) 8 fmt.Println(id, name) 9 } 10 //预处理插入数据 11 stmt2, _ := db.Prepare("insert into product(name,id,price) values(?,?,null)") 12 //name为lisi,id为22 13 rows5, _ := stmt2.Exec("lisi", 22) 14 fmt.Println(rows5.RowsAffected()) 15函数原型func (db *DB) Begin() (*Tx, error)Begin开始一个事务。隔离水平由数据库驱动决定。
1//开启事务 2 tx, _ := db.Begin() 3 //id为1的price+1,id为2的price-1 4 ret4, _ := tx.Exec("update product set price = price + 1 where id = ?", 1) 5 ret5, _ := tx.Exec("update product set price = price - 1 where id = ?", 2) 6 7 //如果id不存在,受影响行数则为0 8 //接收影响行数,为0则失败 9 updNums1, _ := ret4.RowsAffected() 10 updNums2, _ := ret5.RowsAffected() 11 if updNums1 > 0 && updNums2 > 0 { //只有两条更新同时成功,那么才提交 12 tx.Commit() //提交事务 13 fmt.Println("Success") 14 } else { //否则回滚 15 tx.Rollback() //回退事务 16 fmt.Println("Fail") 17 }• tx.Commit() 提交事务• tx.Rollback() 回退事务
demo
1package main 2import ( 3 "database/sql" 4 "fmt" 5 6 _ "github.com/go-sql-driver/mysql" 7) 8type dbWorker struct { 9 dsn string 10 db *sql.DB 11 userInfo usertb 12} 13type usertb struct { 14 id int 15 //NullString代表一个可为NULL的字符串。 16 name sql.NullString 17 //NullInt64代表一个可为NULL的Float64值。 18 price sql.NullFloat64 19} 20func main() { 21 var err error 22 //初始化结构体,保存数据库参数 23 dbw := dbWorker{ 24 dsn: "root:123@/mydb?charset=utf8", 25 } 26 //打开数据库,并保存给结构体内db 27 dbw.db, err = sql.Open("mysql", dbw.dsn) 28 //如果打开失败,panic退出 29 if err != nil { 30 panic(err) 31 } 32 //关闭数据库 33 defer dbw.db.Close() 34 //插入数据 35 dbw.insertData() 36 //获取数据 37 dbw.querData() 38} 39 40//创建方法,插入数据 41func (dbw *dbWorker) insertData() { 42 //预处理,插入数据 43 stmt, _ := dbw.db.Prepare(`INSERT INTO product(name,id,price) VALUES(?,null,?)`) 44 //函数执行完毕,关闭 45 defer stmt.Close() 46 //插入数据 47 ret, err := stmt.Exec("hz", 29) 48 if err != nil { 49 fmt.Println(err) 50 return 51 } 52 //获取id,执行成功,打印 53 if LastInsertId, err := ret.LastInsertId(); err == nil { 54 fmt.Println("LastInsertId:", LastInsertId) 55 } 56 //获取行号,执行成功,打印 57 if RowsAffected, err := ret.RowsAffected(); err == nil { 58 fmt.Println("RowsAffected:", RowsAffected) 59 } 60} 61 62//初始化userInfo 63func (dbw *dbWorker) querDataPre() { 64 dbw.userInfo = usertb{} 65} 66func (dbw *dbWorker) querData() { 67 68 //预处理,查询数据 69 stmt, _ := dbw.db.Prepare(`SELECT * From product where price >= ? AND price < ?`) 70 71 defer stmt.Close() 72 73 dbw.querDataPre() 74 //取price20到30之间的数据 75 rows, err := stmt.Query(20, 30) 76 defer rows.Close() 77 if err != nil { 78 fmt.Println(err) 79 return 80 } 81 for rows.Next(){ 82 //取出数据库数据 83 rows.Scan(&dbw.userInfo.id,&dbw.userInfo.name,&dbw.userInfo.price) 84 if err != nil { 85 fmt.Println(err.Error()) 86 continue 87 } 88 //如果取出的数据为null,则赋一个0值 89 if !dbw.userInfo.name.Valid{ 90 dbw.userInfo.name.String = "" 91 } 92 if !dbw.userInfo.price.Valid{ 93 dbw.userInfo.price.Float64 = 0.00 94 } 95 fmt.Println("get data,id:",dbw.userInfo.id,"name:",dbw.userInfo.name.String,"price",float64(dbw.userInfo.price.Float64)) 96 } 97 err = rows.Err() 98 if err != nil{ 99 fmt.Printf(err.Error()) 100 } 101}版权申明:内容来源网络,版权归原创者所有。除非无法确认,我们都会标明作者及出处,如有侵权烦请告知,我们会立即删除并表示歉意。谢谢。
Golang语言社区
ID:Golangweb
www.ByteEdu.Com
游戏服务器架构丨分布式技术丨大数据丨游戏算法学习