专栏首页Golang语言社区Golang学习笔记之Golang与Mysql交互

Golang学习笔记之Golang与Mysql交互

原文作者:学生黄哲 来源:简书

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{}) *Row QueryRow执行一次查询,并期望返回最多一行结果(即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()受影响的行数

五、修改数据
1//更新数据,修改id>1的行的name
2    ret2, _ := db.Exec("update product set name= '000' where id > ?", 1)
3    //获取影响⾏数
4    aff_nums, _ := ret2.RowsAffected()
5    fmt.Println(aff_nums)
六、删除数据
1  //删除数据,删除id=3的行
2    ret3, _ := db.Exec("delete from product where id = ?",3)
3    delNums, _ := ret3.RowsAffected()
4    fmt.Println(delNums)
5
七、预处理

函数原型 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语言社区(Golangweb)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-12-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • gRPC服务发现&amp;负载均衡

    构建高可用、高性能的通信服务,通常采用服务注册与发现、负载均衡和容错处理等机制实现。根据负载均衡实现所在的位置不同,通常可分为以下三种解决方案:

    李海彬
  • Go语言基础:深入理解 struct 内嵌 inteface

    对于 struct 内嵌 inteface 的使用,我是研究好半天才搞懂,这里记录下我疑问: 1. 如何更好的理解匿名接口 // 匿名接口可以被用作变量或者...

    李海彬
  • go语言操作redis连接池的方法

    unc newPool(server, password string) *redis.Pool { return &redis.Pool{ ...

    李海彬
  • 如何计算子网掩码

    本文提供视频讲解,详细见:(https://www.bilibili.com/video/BV1oT4y17745)

    研究僧
  • 我的VIM配置

    jeremyxu
  • 安全圈年终大趴,FIT 2019首日盛况全程回顾

    对于网络安全行业来说,一年一度的FIT 大会是一次年终的回顾和展望,与业内大咖共同探讨未来的网络安全发展方向以及应对措施;对于无数的白帽子、极客来说,FIT 2...

    FB客服
  • Python不是Java (zt)

    作者:Phillip J. Eby. 翻译:ShiningRay @ NirvanaStudio 原文地址:[[[url]http://dirtsimple...

    py3study
  • 计算树的深度

    windseek
  • IOS开发 图形绘制,绘制线条,矩形,和垂直和居中绘制文字

    假设把上面的方法放入到一个类 DrawUtil 中,我们可以通过 DrawUtil 来调用方法。

    zhangyunfeiVir
  • 美团大佬的零基础算法学习之路

    研究生三年,作为一名非计算机专业的学生,能够从一名纯小白(Python不会,机器学习没听说过)到最后校招拿到几个不错的offer,个人感觉可以给自己打个及格分吧...

    叫我龙总

扫码关注云+社区

领取腾讯云代金券