Go Mysql

Go Mysql,第1张

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:%v\n", 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:%v\n", err)
		return
	}
	fmt.Printf("id:%d name:%s age:%d\n", 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:%v\n", 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:%v\n", err)
	return
}
n, err := ret.RowsAffected() //  *** 作影响的行数
if err != nil {
	fmt.Printf("get RowsAffected failed, err:%v\n", err)
	return
}
fmt.Printf("update success, affected rows:%d\n", n)

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

sqlStr := "delete from user where id = ?"
ret, err := db.Exec(sqlStr, 3)
if err != nil {
	fmt.Printf("delete failed, err:%v\n", err)
	return
}
n, err := ret.RowsAffected() //  *** 作影响的行数
if err != nil {
	fmt.Printf("get RowsAffected failed, err:%v\n", err)
	return
}
fmt.Printf("delete success, affected rows:%d\n", 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:%v\n", err)
	return
}
defer stmt.Close()
rows, err := stmt.Query(0)
if err != nil {
	fmt.Printf("query failed, err:%v\n", 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:%v\n", err)
		return
	}
	fmt.Printf("id:%d name:%s age:%d\n", 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:%v\n", err)
		return
	}
	defer stmt.Close()
	_, err = stmt.Exec("小王子", 18)
	if err != nil {
		fmt.Printf("insert failed, err:%v\n", err)
		return
	}
	_, err = stmt.Exec("沙河娜扎", 18)
	if err != nil {
		fmt.Printf("insert failed, err:%v\n", 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:%v\n", 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:%v\n", err)
	return
}
affRow1, err := ret1.RowsAffected()
if err != nil {
	tx.Rollback() // 回滚
	fmt.Printf("exec ret1.RowsAffected() failed, err:%v\n", 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:%v\n", err)
	return
}
affRow2, err := ret2.RowsAffected()
if err != nil {
	tx.Rollback() // 回滚
	fmt.Printf("exec ret1.RowsAffected() failed, err:%v\n", 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:%v\n", 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:%v\n", err)
	return
}
fmt.Printf("id:%d name:%s age:%d\n", 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:%v\n", err)
	return
}
fmt.Printf("users:%#v\n", users)
插入、更新和删除
// 插入数据
func insertRowDemo() {
	sqlStr := "insert into user(name, age) values (?,?)"
	ret, err := db.Exec(sqlStr, "沙河小王子", 19)
	if err != nil {
		fmt.Printf("insert failed, err:%v\n", err)
		return
	}
	theID, err := ret.LastInsertId() // 新插入数据的id
	if err != nil {
		fmt.Printf("get lastinsert ID failed, err:%v\n", 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:%v\n", err)
		return
	}
	n, err := ret.RowsAffected() //  *** 作影响的行数
	if err != nil {
		fmt.Printf("get RowsAffected failed, err:%v\n", err)
		return
	}
	fmt.Printf("update success, affected rows:%d\n", n)
}

// 删除数据
func deleteRowDemo() {
	sqlStr := "delete from user where id = ?"
	ret, err := db.Exec(sqlStr, 6)
	if err != nil {
		fmt.Printf("delete failed, err:%v\n", err)
		return
	}
	n, err := ret.RowsAffected() //  *** 作影响的行数
	if err != nil {
		fmt.Printf("get RowsAffected failed, err:%v\n", err)
		return
	}
	fmt.Printf("delete success, affected rows:%d\n", 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:%v\n", err)
	return
}
defer rows.Close()
for rows.Next(){
	var u user
	err := rows.StructScan(&u)
	if err != nil {
		fmt.Printf("scan failed, err:%v\n", err)
		continue
	}
	fmt.Printf("user:%#v\n", u)
}

u := user{
	Name: "七米",
}
// 使用结构体命名查询,根据结构体字段的 db tag进行映射
rows, err = db.NamedQuery(sqlStr, u)
if err != nil {
	fmt.Printf("db.NamedQuery failed, err:%v\n", err)
	return
}
defer rows.Close()
for rows.Next(){
	var u user
	err := rows.StructScan(&u)
	if err != nil {
		fmt.Printf("scan failed, err:%v\n", err)
		continue
	}
	fmt.Printf("user:%#v\n", u)
}
事务 *** 作
tx, err := db.Beginx() // 开启事务
if err != nil {
	fmt.Printf("begin trans failed, err:%v\n", 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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/994941.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存