golang操作mysql基础驱动github.com/go-sql-driver/mysql使用
golang中类似java操作mysql的jdbc一样,github.com/go-sql-driver/mysql也为go提供了基础接口,在开发中往往需要写更多的代码来满足自己的定制需求,java在驱动基础上有了扩展,orm框架诞生,mybatis、jpa等都是好用的扩展框架,go也不例外除了知道基础框架的实现和使用外,其他的orm框架也要轻松上手知道他们怎么在基础之上实现的,是否自己实现一套框架,go中的mysql框架比较多,这意味着基础框架github.com/go-sql-driver/mysql做的相当优秀,上层可以i灵活且自由的实现,我们这次主要是复习基础驱动的使用,如下:
package main
import (
"database/sql"
"fmt"
"log"
"time"
_ "github.com/go-sql-driver/mysql"
)
// 用户表结构体
type User struct {
id int64 `db:"id"`
name string `db:"name"`
password string `db:"password"`
age int `db:"age"`
}
var MysqlDb *sql.DB
var MysqlDbErr error
const (
USER_NAME = "root"
PASS_WORD = "fbw123"
HOST = "localhost"
PORT = "3307"
DATABASE = "node"
CHARSET = "utf8"
)
func linksql() {
dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=%s", USER_NAME, PASS_WORD, HOST, PORT, DATABASE, CHARSET)
// 打开连接失败
MysqlDb, MysqlDbErr = sql.Open("mysql", dbDSN)
//defer MysqlDb.Close();
if MysqlDbErr != nil {
log.Println("dbDSN: " + dbDSN)
panic("数据源配置不正确: " + MysqlDbErr.Error())
}
// 最大连接数
MysqlDb.SetMaxOpenConns(100)
// 闲置连接数
MysqlDb.SetMaxIdleConns(20)
// 最大连接周期
MysqlDb.SetConnMaxLifetime(100 * time.Second)
if MysqlDbErr = MysqlDb.Ping(); nil != MysqlDbErr {
panic("数据库链接失败: " + MysqlDbErr.Error())
} else {
fmt.Println("数据库连接成功")
}
}
// 查询数据,指定字段名---完成
func StructQueryField(id int64) {
user := new(User)
row := MysqlDb.QueryRow("select id, name, age,password from user where id=?", id)
if err := row.Scan(&user.id, &user.name, &user.age, &user.password); err != nil {
fmt.Printf("scan failed, err:%v", err)
fmt.Println("查询失败")
return
}
fmt.Println(user.id, user.name, user.age, user.password)
}
// 查询数据,取所有字段-----完成
func StructQueryAllField() {
// 通过切片存储
users := make([]User, 0)
//分页查询一次查询2个记录
rows, _ := MysqlDb.Query("SELECT * FROM `user` limit ?", 2)
// 遍历
var user User
for rows.Next() {
rows.Scan(&user.id, &user.name, &user.age, &user.password)
users = append(users, user)
}
fmt.Println(users)
}
// 插入数据-----完成
func StructInsert(id int, name string, age int8, password string) {
ret, _ := MysqlDb.Exec("insert INTO user(id,name,age,password) values(?,?,?,?)", id, name, age, password)
//插入数据的主键id
lastInsertID, _ := ret.LastInsertId()
fmt.Println("LastInsertID:", lastInsertID)
//影响行数
rowsaffected, _ := ret.RowsAffected()
fmt.Println("RowsAffected:", rowsaffected)
}
// 更新数据 -------完成
func StructUpdate(id int64, name string, password string, age int8) {
ret, _ := MysqlDb.Exec("UPDATE user set name=?,password=?,age=? where id=?", name, password, age, id)
upd_nums, _ := ret.RowsAffected()
fmt.Println("RowsAffected:", upd_nums)
}
// 删除数据------完成
func StructDeluserByid(id uint64) {
ret, _ := MysqlDb.Exec("delete from user where id=?", id)
del_nums, _ := ret.RowsAffected()
fmt.Println("RowsAffected:", del_nums)
}
// 事务处理,结合预处理----完成
func StructTx() {
//事务处理,前面的插入代码没有什么问题,在后面的条件不满足下事务回滚
tx, _ := MysqlDb.Begin()
// 新增
userAddPre, _ := MysqlDb.Prepare("insert into user(name,password,age) values(?, ?,?)")
addRet, _ := userAddPre.Exec("zhaoliu", "mima", 12)
ins_nums, _ := addRet.RowsAffected()
// 更新
userUpdatePre1, _ := tx.Exec("update user set name = 'zhansan' where name=?", "张三")
upd_nums1, _ := userUpdatePre1.RowsAffected()
userUpdatePre2, _ := tx.Exec("update user set name = 'lisi' where name=?", "李四")
upd_nums2, _ := userUpdatePre2.RowsAffected()
fmt.Println(ins_nums)
fmt.Println(upd_nums1)
fmt.Println(upd_nums2)
if ins_nums > 0 && upd_nums1 > 0 && upd_nums2 > 0 {
tx.Commit()
} else {
tx.Rollback()
}
}
// 查询数据,指定字段名,不采用结构体 ------完成
func RawQueryField() {
rows, _ := MysqlDb.Query("select id,name from user")
if rows == nil {
return
}
id := 0
name := ""
fmt.Println(rows)
for rows.Next() {
rows.Scan(&id, &name)
fmt.Println(id, name)
}
}
// 查询数据,取所有字段,不采用结构体------完成
func RawQueryAllField() {
//查询数据,取所有字段
rows2, _ := MysqlDb.Query("select * from user")
//返回所有列
cols, _ := rows2.Columns()
//这里表示一行所有列的值,用[]byte表示
vals := make([][]byte, len(cols))
//这里表示一行填充数据
scans := make([]interface{}, len(cols))
//这里scans引用vals,把数据填充到[]byte里
for k, _ := range vals {
scans[k] = &vals[k]
}
i := 0
result := make(map[int]map[string]string)
for rows2.Next() {
//填充数据
rows2.Scan(scans...)
//每行数据
row := make(map[string]string)
//把vals中的数据复制到row中
for k, v := range vals {
key := cols[k]
//这里把[]byte数据转成string
row[key] = string(v)
}
//放入结果集
result[i] = row
i++
}
fmt.Println(result)
for k, v := range result {
fmt.Println(k, v)
//每条属性打一遍
for k, p := range v {
fmt.Println(k, p)
}
}
}
func main() {
linksql()
// StructQueryField(2020110131)
// StructInsert(100,"lv"",23 "wenli")
// StructQueryAllField()
// StructUpdate(100,"少年","wjr",20)
// StructDeluserByid(100)
// StructTx()
//查询所有的数据显示指定字段
// RawQueryField()
RawQueryAllField()
}