Go语言中mysql数据库操作

释放双眼,带上耳机,听听看~!

数据的持久化是程序中必不可少的,所以编程语言中对数据库的操作是非常重要的一块,本文介绍Go语言对mysql数据库的操作。

基本操作

建立连接

db, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/betting?charset=utf8")errDeal("连接数据库", err)defer db.Close()

连接参数一般有以下几种

user@unix(/path/to/socket)/dbname?charset=utf8user:password@tcp(localhost:5555)/dbname?charset=utf8user:password@/dbnameuser:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname

增删改操作

// 插入数据---------------------方法1result, err := db.Exec("INSERT INTO admin_log(admin_username,log_time,log_ip,log_type,log_desc)" +" VALUES(?,now(),?,?,?)", "admin", "127.0.0.1", "登录", "登录成功")errDeal("插入数据", err)// 查看返回信息count, err := result.RowsAffected()errDeal("查看插入数据条数", err)fmt.Printf("插入数据条数:%d/n", count)id, err := result.LastInsertId()errDeal("查看最后插入数据的id", err)fmt.Printf("最后插入数据的id:%d/n", id)// 插入数据---------------------方法2,先创建一个预处理语句,再执行stmt, err := db.Prepare("INSERT INTO admin_log(admin_username,log_time,log_ip,log_type,log_desc)" +" VALUES(?,now(),?,?,?)")result1, err1 := stmt.Exec("admin", "127.0.0.1", "登录", "登录成功")errDeal("方法2插入数据", err1)fmt.Println(result1.LastInsertId())// 删除数据result2, err := db.Exec("DELETE FROM admin_log WHERE id=?", 2014)fmt.Println(result2.RowsAffected())// 更新数据result3, err := db.Exec("UPDATE admin_log SET log_ip=? WHERE id=?", "192.168.8.9", 2017)fmt.Println(result3.RowsAffected())

单条数据查询

// 先定义存储查询结果的变量var rid intvar username, time, ip, logType stringvar desc, remark, spare interface{} // 如果字段中可能出现值为nil的情况,可以将变量申明为interface{}类型err2 := db.QueryRow("SELECT id,admin_username,log_time,log_ip,log_type,log_desc,remark,spare" +    " FROM admin_log WHERE id=?", 2017).Scan(&rid, &username, &time, &ip, &logType, &desc, &remark, &spare) // 传入的是变量的指针errDeal("查询单条数据", err2)fmt.Printf("id=%d,username=%s,time=%s,ip=%s,logType=%s,desc=%s,remark=%v,spare=%v/n", rid, username, time, ip, logType, desc, remark, spare)

多条数据查询

// 查询多条数据rows, err3 := db.Query("SELECT admin_username,log_time,log_ip,log_type,log_desc" +    " FROM admin_log WHERE id=? OR id=?", 2017, 2019)errDeal("查询多条数据", err3)// 对多条数据进行遍历for rows.Next() {    err4 := rows.Scan(&username, &time, &ip, &logType, &desc)    errDeal("遍历多条数据", err4)    fmt.Printf("username=%s,time=%s,ip=%s,logType=%s,desc=%s/n", username, time, ip, logType, desc)}// 如果查询中不指定具体字段,使用*rows, err33 := db.Query("SELECT *" +    " FROM admin_log WHERE id>?", 2017)errDeal("查询多条数据", err33)// 查询所有字段名,返回string切片columes, err333 := rows.Columns()errDeal("rows.Columns()方法调用", err333)fmt.Printf("%T----%v/n", columes, columes)var scanColumes = make([]interface{}, len(columes))var values = make([]interface{}, len(columes))for index, _ := range  scanColumes {    scanColumes[index] = &values[index]}for rows.Next() {    err4 := rows.Scan(scanColumes...)    errDeal("遍历多条数据", err4)    for i, val := range values {        if strings.EqualFold(judgeType(val), "[]uint8") {            fmt.Printf("%s(%T)==%s/t", columes[i], val, val)        } else {            fmt.Printf("%s(%T)==%v/t", columes[i], val, val)        }    }    fmt.Println()}

事务

开启事务

// 开启事务,tx是从连接池中取出一个连接,在关闭之前都是使用这个连接,提交事务和回滚事务都是操作txtx, err5 := db.Begin()errDeal("开启事务", err5)_, err6 := tx.Exec("UPDATE admin_log SET log_desc=? WHERE id=?", "测试事务222", 2019)//if err6 != nil {if err6 == nil {    tx.Rollback() // 回滚}tx.Commit() // 提交

批量插入数据

// 批量数据插入tx, err7 := db.Begin()errDeal("数据批量插入,开启事务", err7)insertValues := [][]interface{}{{"admin", "127.0.0.1", "登录", "登录成功"},{"admin", "127.0.0.1", "删除", "删除数据"},{"admin", "127.0.0.1", "退出", "退出系统"}}stmt, err8 := tx.Prepare("INSERT INTO admin_log(admin_username,log_time,log_ip,log_type,log_desc) VALUES(?,now(),?,?,?)")errDeal("数据批量插入,预处理", err8)for _, val := range  insertValues {    _, err := stmt.Exec(val...)    if err != nil {        fmt.Printf("出现错误回滚,错误信息:%v", err)        tx.Rollback()    }}tx.Commit()

sqlx的使用及批量插入

xdb, err9 := sqlx.Open("mysql", "root:root@tcp(127.0.0.1:3306)/betting?charset=utf8")errDeal("sqlx连接数据库", err9)txx, err10 := xdb.Beginx()errDeal("sqlx开启事务", err10)insertValuesx := [][]interface{}{{"admin", "127.0.0.1", "登录", "登录成功X"},{"admin", "127.0.0.1", "删除", "删除数据X"},{"admin", "127.0.0.1", "退出", "退出系统X"}}stmtx, err11 := txx.Preparex("INSERT INTO admin_log(admin_username,log_time,log_ip,log_type,log_desc) VALUES(?,now(),?,?,?)")errDeal("数据批量插入,预处理", err11)for _, val := range insertValuesx {    _, err := stmtx.Exec(val...)    if err != nil {        fmt.Printf("sqlx出现错误回滚,错误信息:%v", err)        txx.Rollback()    }}txx.Commit()

完整代码

package mainimport (    "database/sql"    _"github.com/go-sql-driver/mysql" // 这里很重要,导入自己本地使用的数据库驱动,前面是下划线,否则会报错:sql: unknown driver "mysql" (forgotten import?)    "fmt"    "strings"    "github.com/jmoiron/sqlx")func main() {    // 连接数据库,用户名:密码@协议(地址:端口)/数据库?参数=参数值,常用"用户名:密码@tcp(ip:端口)/数据库名?charset=字符集"    db, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/betting?charset=utf8")    errDeal("连接数据库", err)    defer db.Close()    //=========================================================================================增删改    // 插入数据---------------------方法1    result, err := db.Exec("INSERT INTO admin_log(admin_username,log_time,log_ip,log_type,log_desc)" +        " VALUES(?,now(),?,?,?)", "admin", "127.0.0.1", "登录", "登录成功")    errDeal("插入数据", err)    // 查看返回信息    count, err := result.RowsAffected()    errDeal("查看插入数据条数", err)    fmt.Printf("插入数据条数:%d/n", count)    id, err := result.LastInsertId()    errDeal("查看最后插入数据的id", err)    fmt.Printf("最后插入数据的id:%d/n", id)    // 插入数据---------------------方法2,先创建一个预处理语句,再执行    stmt, err := db.Prepare("INSERT INTO admin_log(admin_username,log_time,log_ip,log_type,log_desc)" +        " VALUES(?,now(),?,?,?)")    result1, err1 := stmt.Exec("admin", "127.0.0.1", "登录", "登录成功")    errDeal("方法2插入数据", err1)    fmt.Println(result1.LastInsertId())    // 删除数据    result2, err := db.Exec("DELETE FROM admin_log WHERE id=?", 2014)    fmt.Println(result2.RowsAffected())    // 更新数据    result3, err := db.Exec("UPDATE admin_log SET log_ip=? WHERE id=?", "192.168.8.9", 2017)    fmt.Println(result3.RowsAffected())    //=============================================================================================查询    // 查询单条数据    // 先定义存储查询结果的变量    var rid int    var username, time, ip, logType string    var desc, remark, spare interface{} // 如果字段中可能出现值为nil的情况,可以将变量申明为interface{}类型    err2 := db.QueryRow("SELECT id,admin_username,log_time,log_ip,log_type,log_desc,remark,spare" +        " FROM admin_log WHERE id=?", 2017).Scan(&rid, &username, &time, &ip, &logType, &desc, &remark, &spare) // 传入的是变量的指针    errDeal("查询单条数据", err2)    fmt.Printf("id=%d,username=%s,time=%s,ip=%s,logType=%s,desc=%s,remark=%v,spare=%v/n", rid, username, time, ip, logType, desc, remark, spare)    // 查询多条数据    rows, err3 := db.Query("SELECT admin_username,log_time,log_ip,log_type,log_desc" +        " FROM admin_log WHERE id=? OR id=?", 2017, 2019)    errDeal("查询多条数据", err3)    // 对多条数据进行遍历    for rows.Next() {        err4 := rows.Scan(&username, &time, &ip, &logType, &desc)        errDeal("遍历多条数据", err4)        fmt.Printf("username=%s,time=%s,ip=%s,logType=%s,desc=%s/n", username, time, ip, logType, desc)    }    // 如果查询中不指定具体字段,使用*    rows, err33 := db.Query("SELECT *" +        " FROM admin_log WHERE id>?", 2017)    errDeal("查询多条数据", err33)    // 查询所有字段名,返回string切片    columes, err333 := rows.Columns()    errDeal("rows.Columns()方法调用", err333)    fmt.Printf("%T----%v/n", columes, columes)    var scanColumes = make([]interface{}, len(columes))    var values = make([]interface{}, len(columes))    for index, _ := range  scanColumes {        scanColumes[index] = &values[index]    }    for rows.Next() {        err4 := rows.Scan(scanColumes...)        errDeal("遍历多条数据", err4)        for i, val := range values {            if strings.EqualFold(checkType(val), "[]uint8") {                fmt.Printf("%s(%T)==%s/t", columes[i], val, val)            } else {                fmt.Printf("%s(%T)==%v/t", columes[i], val, val)            }        }        fmt.Println()    }    // ==================================================================================================事务    // 开启事务,tx是从连接池中取出一个连接,在关闭之前都是使用这个连接,提交事务和回滚事务都是操作tx    tx, err5 := db.Begin()    errDeal("开启事务", err5)    _, err6 := tx.Exec("UPDATE admin_log SET log_desc=? WHERE id=?", "测试事务222", 2019)    //if err6 != nil {    if err6 == nil {        tx.Rollback() // 回滚    }    tx.Commit() // 提交    // 批量数据插入    tx, err7 := db.Begin()    errDeal("数据批量插入,开启事务", err7)    insertValues := [][]interface{}{{"admin", "127.0.0.1", "登录", "登录成功"},{"admin", "127.0.0.1", "删除", "删除数据"},{"admin", "127.0.0.1", "退出", "退出系统"}}    stmt, err8 := tx.Prepare("INSERT INTO admin_log(admin_username,log_time,log_ip,log_type,log_desc) VALUES(?,now(),?,?,?)")    errDeal("数据批量插入,预处理", err8)    defer stmt.Close()    // 通过循环将每条SQL的参数写到目标表缓冲区。    for _, val := range  insertValues {        _, err := stmt.Exec(val...)        if err != nil {            fmt.Printf("出现错误回滚,错误信息:%v", err)            tx.Rollback()        }    }    tx.Commit()    // 使用sqlx批量数据插入    xdb, err9 := sqlx.Open("mysql", "root:root@tcp(127.0.0.1:3306)/betting?charset=utf8")    errDeal("sqlx连接数据库", err9)    defer xdb.close()    txx, err10 := xdb.Beginx()    errDeal("sqlx开启事务", err10)    insertValuesx := [][]interface{}{{"admin", "127.0.0.1", "登录", "登录成功X"},{"admin", "127.0.0.1", "删除", "删除数据X"},{"admin", "127.0.0.1", "退出", "退出系统X"}}    stmtx, err11 := txx.Preparex("INSERT INTO admin_log(admin_username,log_time,log_ip,log_type,log_desc) VALUES(?,now(),?,?,?)")    errDeal("数据批量插入,预处理", err11)    defer stmtx.Close()    // 通过循环将每条SQL的参数写到目标表缓冲区。    for _, val := range insertValuesx {        _, err := stmtx.Exec(val...)        if err != nil {            fmt.Printf("sqlx出现错误回滚,错误信息:%v", err)            txx.Rollback()        }    }    txx.Commit()}func errDeal(info string, err error) {    if err != nil {        panic(fmt.Sprintf("%s,错误信息:%v", info, err))    }}func checkType(val interface{}) string {    switch val.(type) {    case []uint8 :        return "[]uint8"    }    return ""}

【转自慕课】https://www.imooc.com

Go

Go(5 [struct | tag | 方法 | 继承 ])

2022-3-3 3:43:17

Go

使用beego框架开发个人博客(三)

2022-3-3 3:50:35

搜索