栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Go语言

Go Mysql

Go语言 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Go Mysql

go语言中的database/sql包提供了保证SQL或类SQL数据库的泛用接口,并不提供具体的数据库驱动。使用database/sql包时必须注入(至少)一个数据库驱动。

Go操作MySQL

go get -u github.com/go-sql-driver/mysql

连接数据库
import (
	"database/sql"

	_ "github.com/go-sql-driver/mysql"
)

func main() {
	dsn := "user:password@tcp(127.0.0.1:3306)/databaseName"
	// Open只检查dsn语法是否有误
	db, err := sql.Open("mysql", dsn)
	if err != nil {
		panic(err)
	}
	defer db.Close()
	// 通没通ping一下就知道!
	err = db.Ping()
	if err != nil {
		return err
	}
}
设置连接池参数
func (db *DB) SetMaxOpenConns(n int)
SetMaxOpenConns设置与数据库建立连接的最大数目。 如果n大于0且小于最大闲置连接数,会将最大闲置连接数减小到匹配最大开启连接数的限制。 如果n<=0,不会限制最大开启连接数,默认为0(无限制)。

func (db *DB) SetMaxIdleConns(n int)
SetMaxIdleConns设置连接池中的最大闲置连接数。 如果n大于最大开启连接数,则新的最大闲置连接数会减小到匹配最大开启连接数的限制。 如果n<=0,不会保留闲置连接。
CRUD前提
type userInfo struct {
	id   int
	age  int
	name string
}
查询 单行查询
func (db *DB) QueryRow(query string, args ...interface{}) *Row
---------------------------------------------------------------
//构造查询语句 使用?当占位符
sqlStr := "select id, name, age from user where id=?"
var u userInfo
err := db.QueryRow(sqlStr, 1).Scan(&u.id, &u.name, &u.age)
// 查询后必须使用Scan,Scan方法内释放了本次连接
if err != nil {
	return
}
多行查询
func (db *DB) Query(query string, args ...interface{}) (*Rows, error)
--------------------------------------------------------------
sqlStr := "select id, name, age from user where id > ?"
rows, err := db.Query(sqlStr, 0)
if err != nil {
	fmt.Printf("query failed, err:%vn", err)
	return
}
// 关闭rows释放持有的数据库链接
defer rows.Close()

// 循环读取结果集中的数据
for rows.Next() {
	var u user
	err := rows.Scan(&u.id, &u.name, &u.age)
	if err != nil {
		fmt.Printf("scan failed, err:%vn", err)
		return
	}
	fmt.Printf("id:%d name:%s age:%dn", u.id, u.name, u.age)
}
插入修改删除数据

插入、更新和删除操作都使用Exec方法。

func (db *DB) Exec(query string, args ...interface{}) (Result, error)
--------------------------------------------------------------
sqlStr := "insert into user(name, age) values (?,?)"
ret, err := db.Exec(sqlStr, "王五", 38)
if err != nil {
	return
}
theID, err := ret.LastInsertId() // 新插入数据的id
if err != nil {
	fmt.Printf("get lastinsert ID failed, err:%vn", err)
	return
}
fmt.Printf("insert success, the id is %d.n", theID)

-------------------------------------------------------------

sqlStr := "update user set age=? where id = ?"
ret, err := db.Exec(sqlStr, 39, 3)
if err != nil {
	fmt.Printf("update failed, err:%vn", err)
	return
}
n, err := ret.RowsAffected() // 操作影响的行数
if err != nil {
	fmt.Printf("get RowsAffected failed, err:%vn", err)
	return
}
fmt.Printf("update success, affected rows:%dn", n)

--------------------------------------------------------------

sqlStr := "delete from user where id = ?"
ret, err := db.Exec(sqlStr, 3)
if err != nil {
	fmt.Printf("delete failed, err:%vn", err)
	return
}
n, err := ret.RowsAffected() // 操作影响的行数
if err != nil {
	fmt.Printf("get RowsAffected failed, err:%vn", err)
	return
}
fmt.Printf("delete success, affected rows:%dn", n)
MySQL预处理
func (db *DB) Prepare(query string) (*Stmt, error)
---------------------------------------------------
sqlStr := "select id, name, age from user where id > ?"
// 预处理
stmt, err := db.Prepare(sqlStr)
if err != nil {
	fmt.Printf("prepare failed, err:%vn", err)
	return
}
defer stmt.Close()
rows, err := stmt.Query(0)
if err != nil {
	fmt.Printf("query failed, err:%vn", err)
	return
}
defer rows.Close()
// 循环读取结果集中的数据
for rows.Next() {
	var u user
	err := rows.Scan(&u.id, &u.name, &u.age)
	if err != nil {
		fmt.Printf("scan failed, err:%vn", err)
		return
	}
	fmt.Printf("id:%d name:%s age:%dn", u.id, u.name, u.age)
}

----------------------------------------------------------------
sqlStr := "insert into user(name, age) values (?,?)"
	stmt, err := db.Prepare(sqlStr)
	if err != nil {
		fmt.Printf("prepare failed, err:%vn", err)
		return
	}
	defer stmt.Close()
	_, err = stmt.Exec("小王子", 18)
	if err != nil {
		fmt.Printf("insert failed, err:%vn", err)
		return
	}
	_, err = stmt.Exec("沙河娜扎", 18)
	if err != nil {
		fmt.Printf("insert failed, err:%vn", err)
		return
	}
	fmt.Println("insert success.")
MySQL事务
func (db *DB) Begin() (*Tx, error)
func (tx *Tx) Commit() error
func (tx *Tx) Rollback() error
---------------------------------------------------------------
tx, err := db.Begin() // 开启事务
if err != nil {
	if tx != nil {
		tx.Rollback() // 回滚
	}
	fmt.Printf("begin trans failed, err:%vn", err)
	return
}
sqlStr1 := "Update user set age=30 where id=?"
ret1, err := tx.Exec(sqlStr1, 2)
if err != nil {
	tx.Rollback() // 回滚
	fmt.Printf("exec sql1 failed, err:%vn", err)
	return
}
affRow1, err := ret1.RowsAffected()
if err != nil {
	tx.Rollback() // 回滚
	fmt.Printf("exec ret1.RowsAffected() failed, err:%vn", err)
	return
}

sqlStr2 := "Update user set age=40 where id=?"
ret2, err := tx.Exec(sqlStr2, 3)
if err != nil {
	tx.Rollback() // 回滚
	fmt.Printf("exec sql2 failed, err:%vn", err)
	return
}
affRow2, err := ret2.RowsAffected()
if err != nil {
	tx.Rollback() // 回滚
	fmt.Printf("exec ret1.RowsAffected() failed, err:%vn", err)
	return
}

fmt.Println(affRow1, affRow2)
if affRow1 == 1 && affRow2 == 1 {
	fmt.Println("事务提交啦...")
	tx.Commit() // 提交事务
} else {
	tx.Rollback()
	fmt.Println("事务回滚啦...")
}

fmt.Println("exec trans success!")
sqlx

sqlx可以认为是Go语言内置database/sql的超集,它在优秀的内置database/sql基础上提供了一组扩展。

安装

go get github.com/jmoiron/sqlx

连接数据库
dsn := "user:password@tcp(127.0.0.1:3306)/databaseName?charset=utf8mb4&parseTime=True"
// 使用Connect是不是对味了?
// 实际上还是Open
db, err = sqlx.Connect("mysql", dsn)
if err != nil {
	fmt.Printf("connect DB failed, err:%vn", err)
	return
}
// Connect内已经ping过了,这里就不用再ping了,闲的没事也可以ping一下
db.SetMaxOpenConns(20)
db.SetMaxIdleConns(10)
查询

由于查询是sqlx完成的,但结构体是在main.go文件中,所以结构体的成员要首字母大写。

单查
sqlStr := "select id, name, age from user where id=?"
var u user
err := db.Get(&u, sqlStr, 1)
if err != nil {
	fmt.Printf("get failed, err:%vn", err)
	return
}
fmt.Printf("id:%d name:%s age:%dn", u.ID, u.Name, u.Age)
多查
sqlStr := "select id, name, age from user where id > ?"
var users []user
// 虽然切片是引用类型,但还是要传指针,即指针的指针
err := db.Select(&users, sqlStr, 0)
if err != nil {
	fmt.Printf("query failed, err:%vn", err)
	return
}
fmt.Printf("users:%#vn", users)
插入、更新和删除
// 插入数据
func insertRowDemo() {
	sqlStr := "insert into user(name, age) values (?,?)"
	ret, err := db.Exec(sqlStr, "沙河小王子", 19)
	if err != nil {
		fmt.Printf("insert failed, err:%vn", err)
		return
	}
	theID, err := ret.LastInsertId() // 新插入数据的id
	if err != nil {
		fmt.Printf("get lastinsert ID failed, err:%vn", err)
		return
	}
	fmt.Printf("insert success, the id is %d.n", theID)
}

// 更新数据
func updateRowDemo() {
	sqlStr := "update user set age=? where id = ?"
	ret, err := db.Exec(sqlStr, 39, 6)
	if err != nil {
		fmt.Printf("update failed, err:%vn", err)
		return
	}
	n, err := ret.RowsAffected() // 操作影响的行数
	if err != nil {
		fmt.Printf("get RowsAffected failed, err:%vn", err)
		return
	}
	fmt.Printf("update success, affected rows:%dn", n)
}

// 删除数据
func deleteRowDemo() {
	sqlStr := "delete from user where id = ?"
	ret, err := db.Exec(sqlStr, 6)
	if err != nil {
		fmt.Printf("delete failed, err:%vn", err)
		return
	}
	n, err := ret.RowsAffected() // 操作影响的行数
	if err != nil {
		fmt.Printf("get RowsAffected failed, err:%vn", err)
		return
	}
	fmt.Printf("delete success, affected rows:%dn", n)
}
扩展操作 NamedExec

DB.NamedExec方法用来绑定SQL语句与结构体或map中的同名字段。

sqlStr := "INSERT INTO user (name,age) VALUES (:name,:age)"
_, err = db.NamedExec(sqlStr,
	map[string]interface{}{
		"name": "七米",
		"age": 28,
	})
return
NamedQuery

与DB.NamedExec同理,这里是支持查询。

sqlStr := "SELECT * FROM user WHERe name=:name"
// 使用map做命名查询
rows, err := db.NamedQuery(sqlStr, map[string]interface{}{"name": "七米"})
if err != nil {
	fmt.Printf("db.NamedQuery failed, err:%vn", err)
	return
}
defer rows.Close()
for rows.Next(){
	var u user
	err := rows.StructScan(&u)
	if err != nil {
		fmt.Printf("scan failed, err:%vn", err)
		continue
	}
	fmt.Printf("user:%#vn", u)
}

u := user{
	Name: "七米",
}
// 使用结构体命名查询,根据结构体字段的 db tag进行映射
rows, err = db.NamedQuery(sqlStr, u)
if err != nil {
	fmt.Printf("db.NamedQuery failed, err:%vn", err)
	return
}
defer rows.Close()
for rows.Next(){
	var u user
	err := rows.StructScan(&u)
	if err != nil {
		fmt.Printf("scan failed, err:%vn", err)
		continue
	}
	fmt.Printf("user:%#vn", u)
}
事务操作
tx, err := db.Beginx() // 开启事务
if err != nil {
	fmt.Printf("begin trans failed, err:%vn", err)
	return err
}
defer func() {
	if p := recover(); p != nil {
		tx.Rollback()
		panic(p) // re-throw panic after Rollback
	} else if err != nil {
		fmt.Println("rollback")
		tx.Rollback() // err is non-nil; don't change it
	} else {
		err = tx.Commit() // err is nil; if Commit returns error update err
		fmt.Println("commit")
	}
}()
sqlx.In 使用sqlx.In实现批量插入
query, args, _ := sqlx.In(
		"INSERT INTO user (name, age) VALUES (?), (?), (?)",
		[]interface{}{blog1.Site_name, blog1.Site_theme, blog1.Site_title},[]interface{}{},[]interface{}{})
fmt.Println(query) // 查看生成的querystring
fmt.Println(args)  // 查看生成的args
_, err := DB.Exec(query, args...)
return err
sqlx.In的查询
query, args, err := sqlx.In("SELECT name, age FROM user WHERe id IN (?)", ids)
if err != nil {
	return
}
// sqlx.In 返回带 `?` bindvar的查询语句, 我们使用Rebind()重新绑定它
query = DB.Rebind(query)

err = DB.Select(&users, query, args...)
return
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/906346.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号