其他分享
首页 > 其他分享> > Go_ORM & MQ(待续)

Go_ORM & MQ(待续)

作者:互联网

(相当于Java的MyBatis)

Go操作MySQL

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

下载

下载依赖: go get -u github.com/go-sql-driver/mysql
会保存在$GOPATH/src/目录下

使用MySQL驱动
函数签名

func Open(drivername,dataSourceName string)(*DB ,error)

DB是一个数据库(操作)句柄,代表一个具有零到多个底层连接到连接池。它可以安全的被多个go协程同时使用。
sql包会自动创建和释放连接;它也会维护一个闲置连接的连接池。如果数据库具有单链接状态概念,该状态只有在事务被观察时才可信。一旦调用了DB.Begin,返的回Tx会绑定到单个连接。当事务Tx到Commit或RollBack后,该事务使用的连接会归还到DB中的闲置连接池。

启用

package main

import{
	"database/sql"
	_ "github.com/go-sql-driver/mysql"//导入但不直接使用,相当于使用init()方法
}

func main(){
	//数据库信息
	dataSourceName:="root:123456@tcp(127.0.0.1:3306)/database"//用户名:密码
	//连接数据库
	db,err:=sql.Open("mysql",dataSourceName)//不会校验用户名密码,只会校验格式。
	if err!=nil{//格式不正确报错
		fmt.Println("open failed,error:%v",err)
	}
	err=db.Ping()
	if err!=nil{//密码不正确报错
		fmt.Println("open failed,error:%v",err)
	}
}

如果写在main函数中,当在其他函数写query或者insert的时候,无法使用main中的变量。
所以应该把变量定义在main之外

增删改查

package main

import{
	"database/sql"
	_ "github.com/go-sql-driver/mysql"//导入但不直接使用,相当于使用init()方法
}

var db *sql.DB
func initDB(err error){
	//数据库信息
	dataSourceName:="root:123456@tcp(127.0.0.1:3306)/database"//用户名:密码@端口
	//连接数据库
	db,err=sql.Open("mysql",dataSourceName)//注意没有:冒号
	if err!=nil{//格式不正确报错
		return	
	}
	err=db.Ping()
	if err!=nil{//密码不正确报错
		return	
	}
	//设置数据库连接池最大连接数,用完之后新来的会等待
	db.SetMaxOpenConns(10)//可以省略不写
	return
}

//结构体
type user struct{
	ig int
	name string
	age int
}

func main(){
	err:=initDB()
	if err!=nil{
		fmt.Println("Db init failed,err",err)
	}
	fmt.Println("链接数据库成功")
	
	//查询单条记录db.QueryRow方法
	sqlStr:="select * from user where id=1;"
	rowObj:=db.QueryRow(sqlStr)//从连接池拿一个连接出来去数据库查询单挑记录,返回的是Row对象
	//动态查询
	//sqlStr:="select * from user where id=?;"
	//rowObj:=db.QueryRow(sqlStr,1)
	var u1 user
	rowObj.Scan(&u1.id,&u1.name,&u1.age)//使用完之后会自动关闭连接
	fmt.Println("u1:%v",u1)

	//查询多条记录db.Query方法
	sqlStr2:="select * from user where id>1;"
	rows,err:=db.Query(sqlStr2)
	if err!=nil{
		fmt.Println("error")
	}
	defer rows.Close()//重要,需要手动关闭
	//读取结果
	for rows.Next(){
		var u user
		err:=rows.Scan(&u1.id,&u1.name,&u1.age)
	}

	//插入、更新、删除数据db.Exec方法
	sqlStr3:="insert into user(name,age) values (?,?)"
	ret,err:=db.Exec(sqlStr3,"Kramer",24)
	if err != nill{
		fmt.Println("error")
	}
	theID,err:=ret.LastInsertId()//新插入数据的id
	//n,err:=ret.RowsAffected()//受影响的行数
	if err != nill{
		fmt.Println("error")
	}
	fmt.Println("insert success,ID:",theID)
}

MySQL预处理

普通SQL语句执行过程:
1、SQL语句进行占位符替换得到完整SQL语句
2、客户端发送完整SQL语句到MySQL服务端
3、MySQL服务端执行完整SQL语句并返回结果给客户端

预处理执行过程:
1、把SQL语句拆分成两部分,命令部分和数据部分
2、先把命令部分发送给MySQL服务端,MySQL服务端进行SQL预处理
3、把数据部分发送给MySQL服务端,MySQL服务端对SQL语句进行占位符替换
4、MySQL服务端执行完整SQL语句并返回结果给客户端

预处理好处:
优化MySQL服务器重复执行SQL对方法,提升服务器性能,
避免SQL注入问题

适用范围:频繁使用的SQL语句

Go实现MySQL预处理

语法:func (db *DB)Prepare(query string)(*Stmt,error)
Prepare方法先将sql语句发送给MySQL服务端,返回一个准备好的状态用于止呕的查询和命令。返回值可以同时执行多个查询和命令。

func prepareQueryDemo(){
	sqlStr;="select * from user where id>?"
	stmt,err:=db.Prepare(sqlStr)
	if err != nill{
		fmt.Println("error")
		return
	}
	defer stmt.Close()//重要
	rows,err:=stmt.Query(0)
	//增删改用stmt.Exec()
	//_,err:=stmt.Exec(xxx,xx,xx...)这行多执行几次完成批量操作
	if err != nill{
		fmt.Println("error")
		return
	}
	defer rows.Close()//重要,需要手动关闭
	//循环读取结果集中的数据
	for rows.Next(){
		var u user
		err:=rows.Scan(&u1.id,&u1.name,&u1.age)
		if err != nill{
			fmt.Println("error")
			return
		}
		fmt.Println(u)
	}
}

MySQL事务

GO实现MySQL事务

依赖于以下的方法来实现

//开启事务
func (db *DB)Begin()(*Tx,err)

//提交事务
func (tx *Tx)Commit()error

//回滚事务
func (tx *Tx)Rollback()error

示例:

func transactionDemo() {
	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

第三方库,简化操作,提升效率
需要再 import “github.com/jmoiron/sqlx”

注意:结构体字段名需要和数据库字段名对应

//查询单行记录
func queryRowDemo(){
	sqlStr:="select id,name,age from user where id =?"
	var u user
	err:=db.Get(&u,sqlStr,1)//区别在于直接传入变量u
	if err!=nil{
		fmt.Println("error:"err)
		return
	}
	fmt.Printf("n=%v",u)
}

//查询多行记录
func queryMultiRowDemo(){
	sqlStr:="select id,name,age from user where id >?"
	var users []user
	err:=db.Select(&users,sqlStr,0)
		if err!=nil{
		fmt.Println("error:"err)
		return
	}
	fmt.Println("users:%v",users)
}

Redis

连接Redis

使用第三方库https://github.com/go-redis/resdis连接Redis数据库并进行操作。
安装命令:go get -u github.com/go-redis/redis

//声明一个全局的redisdb变量
var redisdb *redis.Client

//初始化连接
func initRedis()(err error){
	redisdb=redis.NewClient(&redis.Options{
		Addr:"localhost:6379",
		Password:"",
		DB:0,
	})

	_,err:=redisdb.Ping().Result()
	if err!=nil{
		return err
	}
	return nil
}

func main(){
	err:=initinitRedis()
	if err!=nil{
		fmt.Println("connect err:",err)
	}
	fmt.Println("connect success ")
}

基本使用

网站

NSQ

分布式消息队列,优点:
1、分布式和分散拓扑,没有单点故障,支持容错和高可用性,并提供可靠的信息交付保证
2、支持横向扩展,没有任何集中式代理
3、易于配置和部署,内置了管理界面

适用场景:
异步操作、应用解耦、流量削峰…

安装

使用

(暂时跳过)

标签:待续,nil,err,fmt,db,Println,ORM,error,Go
来源: https://blog.csdn.net/m0_46199937/article/details/120553294