• go sqlx 包


    go sqlx 包

    1 介绍和使用

    上文我们用了go-sql-driver/mysql库来操作 mysql,还有一个更优秀的库 sqlx,它也是对标准库database/sql具体的实现,并进行进一步封装和新增了一些方法

    1.1 安装和快速链接

    go get -u github.com/jmoiron/sqlx
    
    • 1
    package main
    
    import (
    	"fmt"
    	_ "github.com/go-sql-driver/mysql" // 执行一些初始化操作
    	"github.com/jmoiron/sqlx"
    )
    
    func createDB() (*sqlx.DB, error) {
    	// 1 链接方式一
    	DB1,err := sqlx.Open("mysql","root:Yuxihan@666@tcp(127.0.0.1:3306)/study?charset=utf8")
    	// 2 链接方式二  区别在于MustOpen是真正链接上了mysql, 并发不安全,不推荐使用
    	//DB:=sqlx.MustOpen("mysql","root:Yuxihan@666@tcp(127.0.0.1:3306)/lqz?charset=utf8")
    	if err != nil {
    		fmt.Println("链接出错:",err)
    		return nil,err
    	}
    	err = DB1.Ping()
    	if err!=nil {
    		fmt.Println("通信出错",err)
    		return nil,err
    	}
    	return DB1,nil
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    2 基本增删查改

    go-sql-driver/mysql 包的用法完全兼容

    2.1 增加数据

    // 1 增加数据
    func insertPeople() {
    	sqlStr := "insert into people(name,age,sex) values (?,?,?)"
    	ret, err := DB.Exec(sqlStr, "tony", 23, "男")
    	if err != nil {
    		fmt.Println("插入出错,", err)
    		return
    	}
    	theID, err := ret.LastInsertId() // 新插入数据的id
    	if err != nil {
    		fmt.Println("获取插入的id出错", err)
    		return
    	}
    	fmt.Println("插入成功,id为:", theID)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2.2 修改数据

    // 2 修改数据
    func updatePeople() {
    	sqlStr := "update people set name= ? where id = ?"
    	ret, err := DB.Exec(sqlStr, "jim", 1)
    	if err != nil {
    		fmt.Println("更新失败", err)
    		return
    	}
    	n, err := ret.RowsAffected()
    	if err != nil {
    		fmt.Println("获取影响的行数失败:", err)
    		return
    	}
    	fmt.Println("更新成功,影响行数为:", n)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2.3 删除数据

    // 3 删除数据
    func deletePeople() {
    	sqlStr := "delete from people where id = ?"
    	ret, err := DB.Exec(sqlStr, 5)
    	if err != nil {
    		fmt.Println("删除出错:", err)
    		return
    	}
    	n, err := ret.RowsAffected() // 操作影响的行数
    	if err != nil {
    		fmt.Println("获取操作影响的行数出错:", err)
    		return
    	}
    	fmt.Println("删除成功,影响的行数为:", n)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2.4 查询数据

    type people struct {
    	Id   int
    	Name string
    	Age  int
    	Sex  string
    }
    // 查询数据单条
    func main() {
    	DB,err := createDB()
    	if err != nil {
    		fmt.Println("链接出错:",err)
    	}
    	var people people
    	err = DB.QueryRow("select * from people where id=?",1).Scan(&people.Id,&people.Name,&people.Age,&people.Sex)
        
    	if err != nil {
    		fmt.Println("查询出错:", err)
    	}
    	fmt.Println(people)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    // 查询多条
    func main() {
    	DB,err := createDB()
    	if err != nil {
    		fmt.Println("链接出错:",err)
    	}
    	var people people
    	sqlStr := "select * from people where id > ?"
    	rows, err := DB.Query(sqlStr, 1)
    	if err != nil {
    		fmt.Println("查询出错:", err)
    		return
    	}
    	// 关闭rows释放持有的数据库链接
    	defer rows.Close()
    	// 循环读取结果集中的数据
    	for rows.Next() {
    		err := rows.Scan(&people.Id,&people.Name,&people.Age,&people.Sex)
    		if err != nil {
    			fmt.Println("遍历出错", err)
    			return
    		}
    		fmt.Println(people)
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    3 其他查询

    3.1 Get和Select查询

    func main() {
    	DB,err := createDB()
    	if err != nil {
    		fmt.Println("链接出错:",err)
    	}
    	var people people
    	err = DB1.Get(&people,"select * from people where id=?",1)
    	if err != nil {
    		fmt.Println("查询出错:", err)
    	}
    	fmt.Println(people)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    // Select 查询
    func main() {
    
    	DB,err := createDB()
    	if err != nil {
    		fmt.Println("链接出错:",err)
    	}
    	var people []people
    	err = DB.Select(&people,"select * from people where id > ?",1)
    	if err != nil {
    		fmt.Println("查询出错",err)
    	}
    	fmt.Println(people)
    }    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    4 其他方法

    4.1 sqlx的NamedExec

    传参可使用key-value的形式,不用原来一个问号?对应一个参数
    用来绑定SQL语句与结构体或map中的同名字段

    func main() {
    
    	DB,err := createDB()
    	if err != nil {
    		fmt.Println("链接出错:",err)
    	}
    	sqlStr := "insert into people(name,age,sex) values (:name,:age,:sex)"
    	_, err = DB.NamedExec(sqlStr,
    		map[string]interface{}{
    			"name": "好汉",
    			"age": 14,
    			"sex":"男",
    		})
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    4.2 sqlx的NamedQuery

    支持查询,不仅支持结构体类型的查询,还支持map作为查询名

    // 使用map作为查询名	
    func main() {
    
    	DB,err := createDB()
    	if err != nil {
    		fmt.Println("链接出错:",err)
    	}
    	sqlStr := "SELECT * FROM people WHERE name=:name"
        // 使用map做命名查询
    	rows, _ := DB.NamedQuery(sqlStr, map[string]interface{}{"name": "好汉"})
    	defer rows.Close()
    	for rows.Next(){
    		var m people
    		rows.StructScan(&m)
    		fmt.Println(m)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    5 事务操作

    sqlx提供了db.Beginx()和 tx.Exec()方法进行事务操作

    func main() {
    	DB,err := createDB()
    	if err != nil {
    		fmt.Println("链接出错:",err)
    	}
    	tx, err := DB.Beginx() // 开启事务
    	if err != nil {
    		fmt.Printf("开启事务错误:%v\n", err)
    		return
    	}
    
    	_,err=tx.Exec("insert into people(name, age,sex) values (?,?,?)", "朱一",23,"男")
    	if err != nil {
    		tx.Rollback() // 出错就回滚
    		fmt.Println("出错回滚")
    		return
    	}
    	_,err=tx.Exec("insert into people(name, age,sex) values (?,?,?)", "朱二",23,"男")
    	if err != nil {
    		tx.Rollback() // 出错就回滚
    		fmt.Println("出错回滚")
    		return
    	}
    	tx.Commit()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    6 连接池

    只用 sqlx.Open() 函数创建连接池,此时只是初始化了连接池,并没有连接数据库,连接都是惰性的,只有调用 sqlx.DB 的方法时,此时才真正用到了连接,连接池才会去创建连接,连接池很重要,它直接影响着你的程序行为

    连接池的工作原理也非常简单,当调用 sqlx.DB 的方法时,会首先去向连接池请求要一个数据库连接,如果连接池有空闲的连接,则返回给方法中使用,否则连接池将创建一个新的连接给到方法中使用;一旦将数据库连接给到了方法中,连接就属于方法了。方法执行完毕后,要不把连接所属权还给连接池,要不传递给下一个需要数据库连接的方法中,最后都使用完将连接释放回到连接池中

    db.SetMaxOpenConns(100) // 设置连接池最大连接数
    db.SetMaxIdleConns(20)  // 设置连接池最大空闲连接数
    
    • 1
    • 2
  • 相关阅读:
    【iOS】—— 对象的底层结构和继承者链(isa、class)
    LiveGBS流媒体平台GB/T28181功能-国标设备通道分享手机PC浏览器观看直播
    在VR全景中嵌入3D模型有哪些优势?
    可上手 JVM 调优实战指南
    Android Framework系列---输入法服务
    电商项目之Java8函数式接口落地实践
    U-Net和Graph U-Net
    天池比赛记录
    嵌入式开发:为可重用软件模块设计接口的5个技巧
    图神经网络学习笔记 | 基础知识与 GNN 介绍 直观透彻理解
  • 原文地址:https://blog.csdn.net/qq_55752792/article/details/126272835