sqlx is a library which provides a set of extensions on go's standard database/sql library.

sqlx support some db:  mysql, postgresql, oracle, sqlite ...

https://github.com/jmoiron/sqlx

示例代码:

该库目前只对查询进行了深度封装,对于更新和插入封装较少。

新建表

package main

import (
"database/sql"
_ "github.com/go-sql-driver/mysql" "github.com/jmoiron/sqlx"
) var schema = `Create table person2(
first_name varchar(),
last_name varchar(),
email varchar());
` var schema2 = `Create table place(
country varchar(),
city varchar() NULL,
telcode int());
` type Person struct {
FirstName string `db:"first_name"`
LastName string `db:"last_name"`
Email string
} type Place struct {
Country string
city sql.NullString
TelCode int
} func main() {
dsn := "root:123456@tcp(172.16.65.200:3306)/golang"
db, err := sqlx.Connect("mysql", dsn)
if err != nil {
panic(err)
} result, err := db.Exec(schema2)
if err != nil {
panic(err)
}
_, err = result.RowsAffected()
if err != nil {
panic(err)
} }

单行查询使用 sqlx.Get(),多行查询使用 sqlx.Select()

package main

import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"fmt"
"log"
"github.com/jmoiron/sqlx"
) type User struct {
Id int `db:"id"`
Name string `db:"name"`
Age int `db:"age"`
} // 单行查询,如果查询到多个结果,只返回第一行,查询不到结果就ErrNoRows错误。
func QueryRow(db *sqlx.DB) {
var user User
err := db.Get(&user, "select id, name, age from user where id=?", )
if err == sql.ErrNoRows {
log.Printf("not found data of the id:%d", )
} if err != nil {
panic(err)
} fmt.Printf("user: %#v\n", user)
} // 多行查询, 查询不到任何记录也不会报错。
func Query(db *sqlx.DB) {
var users []*User
err := db.Select(&users, "select id, name, age from user")
if err != nil {
panic(err)
}
if err == sql.ErrNoRows {
log.Printf("not found data")
return
} for _, user := range users {
fmt.Println(user.Id, user.Name)
}
} func main() {
dsn := "root:123456@tcp(172.16.65.200:3306)/golang"
db, err := sqlx.Connect("mysql", dsn)
if err != nil {
panic(err)
} err = db.Ping()
if err != nil {
panic(err)
} fmt.Printf("connect to db success\n") QueryRow(db) Query(db)
}

更新和插入使用sqlx.Exec()

package main

import (
_ "github.com/go-sql-driver/mysql"
"fmt"
"github.com/jmoiron/sqlx"
) func Update(db *sqlx.DB) {
name := "Miles"
age :=
id := result, err := db.Exec("update user set name=?, age=? where id=?", name, age, id)
if err != nil {
panic(err)
} // RowsAffected returns the number of rows affected by an
// update, insert, or delete.
rowsAffected, err := result.RowsAffected()
if err != nil {
panic(err)
} fmt.Printf("update id:%d, affect rows:%d\n", id, rowsAffected) } func Insert(db *sqlx.DB) {
name := "Lucy"
age := result, err := db.Exec("insert into user(name, age) values (?,?)", name, age)
if err != nil {
panic(err)
} id, err := result.LastInsertId()
if err != nil {
panic(err)
} affected, err := result.RowsAffected()
if err != nil {
panic(err)
} fmt.Printf("last insert id:%d affect rows:%d\n", id, affected)
} func main() {
dsn := "root:123456@tcp(172.16.65.200:3306)/golang"
db, err := sqlx.Connect("mysql", dsn)
if err != nil {
panic(err)
} err = db.Ping()
if err != nil {
panic(err)
}
fmt.Println("connect to db success!!!")
Update(db)
Insert(db)
}

预处理,直接使用原生的sql.db,没有进行过任何封装

package main

import (
_ "github.com/go-sql-driver/mysql"
"fmt"
"github.com/jmoiron/sqlx"
) type User2 struct {
Id int `db:"id"`
Name string `db:"name"`
Age int `db:"age"`
} // 预处理是为了提高查询性能;
// 实现的原理是先将查询语句发送给Mysql数据库做预解析;
// 然后再将需要查询的条件数据发送给Mysql数据库进行执行;
// 这种原理类似于GO语言和Python语言执行效率的对比;
// Go语言是需要先编译的,Python是一边执行一边编译。
func PrepareQuery(db *sqlx.DB, id int) {
stmt, err := db.Prepare("select id, name, age from user where id>?")
if err != nil {
panic(err)
} rows, err := stmt.Query(id)
if err != nil {
panic(err)
} defer stmt.Close()
defer rows.Close() for rows.Next(){
var user User2
err := rows.Scan(&user.Id, &user.Name, &user.Age)
if err != nil {
panic(err)
}
fmt.Printf("user: %#v\n", user)
}
} func main() { dsn := "root:123456@tcp(172.16.65.200:3306)/golang"
db, err := sqlx.Connect("mysql", dsn)
if err != nil {
panic(err)
} defer db.Close() PrepareQuery(db, ) }

原则性操作

package main

import (
_ "github.com/go-sql-driver/mysql"
"fmt"
"github.com/jmoiron/sqlx"
) func Transaction(db *sqlx.DB) { // 开启事务
tx, err := db.Begin() if err != nil {
panic(err)
} result, err := tx.Exec("insert into user(name, age)values(?,?)", "Jack", )
if err != nil {
// 失败回滚
tx.Rollback()
panic(err)
} fmt.Println("result", result) exec, err := tx.Exec("update user set name=?, age=? where id=?", "Jack", , )
if err != nil {
// 失败回滚
tx.Rollback()
panic(err)
}
fmt.Println("exec", exec) // 提交事务
err = tx.Commit() if err != nil {
// 失败回滚
tx.Rollback()
panic(err)
}
} func main() { dsn := "root:123456@tcp(172.16.65.200:3306)/golang"
db, err := sqlx.Connect("mysql", dsn)
if err != nil {
panic(err)
} err = db.Ping()
if err != nil {
panic(err)
} Transaction(db)
}

Named

    // Named queries can use structs, so if you have an existing struct (i.e. person := &Person{}) that you have populated, you can pass it in as &person
tx.NamedExec("INSERT INTO person (first_name, last_name, email) VALUES (:first_name, :last_name, :email)", &Person{"Jane", "Citizen", "jane.citzen@example.com"})
tx.Commit()

更多用法

package main

import (
"database/sql"
"fmt"
"log" _ "github.com/lib/pq"
"github.com/jmoiron/sqlx"
) var schema = `
CREATE TABLE person (
first_name text,
last_name text,
email text
); CREATE TABLE place (
country text,
city text NULL,
telcode integer
)` type Person struct {
FirstName string `db:"first_name"`
LastName string `db:"last_name"`
Email string
} type Place struct {
Country string
City sql.NullString
TelCode int
} func main() {
// this Pings the database trying to connect, panics on error
// use sqlx.Open() for sql.Open() semantics
db, err := sqlx.Connect("postgres", "user=foo dbname=bar sslmode=disable")
if err != nil {
log.Fatalln(err)
} // exec the schema or fail; multi-statement Exec behavior varies between
// database drivers; pq will exec them all, sqlite3 won't, ymmv
db.MustExec(schema) tx := db.MustBegin()
tx.MustExec("INSERT INTO person (first_name, last_name, email) VALUES ($1, $2, $3)", "Jason", "Moiron", "jmoiron@jmoiron.net")
tx.MustExec("INSERT INTO person (first_name, last_name, email) VALUES ($1, $2, $3)", "John", "Doe", "johndoeDNE@gmail.net")
tx.MustExec("INSERT INTO place (country, city, telcode) VALUES ($1, $2, $3)", "United States", "New York", "")
tx.MustExec("INSERT INTO place (country, telcode) VALUES ($1, $2)", "Hong Kong", "")
tx.MustExec("INSERT INTO place (country, telcode) VALUES ($1, $2)", "Singapore", "")
// Named queries can use structs, so if you have an existing struct (i.e. person := &Person{}) that you have populated, you can pass it in as &person
tx.NamedExec("INSERT INTO person (first_name, last_name, email) VALUES (:first_name, :last_name, :email)", &Person{"Jane", "Citizen", "jane.citzen@example.com"})
tx.Commit() // Query the database, storing results in a []Person (wrapped in []interface{})
people := []Person{}
db.Select(&people, "SELECT * FROM person ORDER BY first_name ASC")
jason, john := people[], people[] fmt.Printf("%#v\n%#v", jason, john)
// Person{FirstName:"Jason", LastName:"Moiron", Email:"jmoiron@jmoiron.net"}
// Person{FirstName:"John", LastName:"Doe", Email:"johndoeDNE@gmail.net"} // You can also get a single result, a la QueryRow
jason = Person{}
err = db.Get(&jason, "SELECT * FROM person WHERE first_name=$1", "Jason")
fmt.Printf("%#v\n", jason)
// Person{FirstName:"Jason", LastName:"Moiron", Email:"jmoiron@jmoiron.net"} // if you have null fields and use SELECT *, you must use sql.Null* in your struct
places := []Place{}
err = db.Select(&places, "SELECT * FROM place ORDER BY telcode ASC")
if err != nil {
fmt.Println(err)
return
}
usa, singsing, honkers := places[], places[], places[] fmt.Printf("%#v\n%#v\n%#v\n", usa, singsing, honkers)
// Place{Country:"United States", City:sql.NullString{String:"New York", Valid:true}, TelCode:1}
// Place{Country:"Singapore", City:sql.NullString{String:"", Valid:false}, TelCode:65}
// Place{Country:"Hong Kong", City:sql.NullString{String:"", Valid:false}, TelCode:852} // Loop through rows using only one struct
place := Place{}
rows, err := db.Queryx("SELECT * FROM place")
for rows.Next() {
err := rows.StructScan(&place)
if err != nil {
log.Fatalln(err)
}
fmt.Printf("%#v\n", place)
}
// Place{Country:"United States", City:sql.NullString{String:"New York", Valid:true}, TelCode:1}
// Place{Country:"Hong Kong", City:sql.NullString{String:"", Valid:false}, TelCode:852}
// Place{Country:"Singapore", City:sql.NullString{String:"", Valid:false}, TelCode:65} // Named queries, using `:name` as the bindvar. Automatic bindvar support
// which takes into account the dbtype based on the driverName on sqlx.Open/Connect
_, err = db.NamedExec(`INSERT INTO person (first_name,last_name,email) VALUES (:first,:last,:email)`,
map[string]interface{}{
"first": "Bin",
"last": "Smuth",
"email": "bensmith@allblacks.nz",
}) // Selects Mr. Smith from the database
rows, err = db.NamedQuery(`SELECT * FROM person WHERE first_name=:fn`, map[string]interface{}{"fn": "Bin"}) // Named queries can also use structs. Their bind names follow the same rules
// as the name -> db mapping, so struct fields are lowercased and the `db` tag
// is taken into consideration.
rows, err = db.NamedQuery(`SELECT * FROM person WHERE first_name=:first_name`, jason)
}

Go sqlx库的更多相关文章

  1. GO学习-(23) Go语言操作MySQL + 强大的sqlx

    Go语言操作MySQL MySQL是业界常用的关系型数据库,本文介绍了Go语言如何操作MySQL数据库. Go操作MySQL 连接 Go语言中的database/sql包提供了保证SQL或类SQL数据 ...

  2. Golang语言系列-15-数据库

    数据库 MySQL 连接数据库 package main import ( "database/sql" "fmt" _ "github.com/go ...

  3. Go语言基础之16--Mysql基本操作

    一.Mysql驱动及数据库连接 1.1 Golang中的Mysql驱动 A. https://github.com/go-sql-driver/mysql B. Go本身不提供具体数据库驱动,只提供驱 ...

  4. Go 操作 Mysql(一)

    关于 Go 的标准库 database/sql 和 sqlx database/sql 是 Go 操作数据库的标准库之一,它提供了一系列接口方法,用于访问数据库(mysql,sqllite,oralc ...

  5. 18 . Go之操作Mysql和sqlx使用

    安装mysql wget http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm yum -y localinstall ...

  6. sqlx操作MySQL实战及其ORM原理

    sqlx是Golang中的一个知名三方库,其为Go标准库database/sql提供了一组扩展支持.使用它可以方便的在数据行与Golang的结构体.映射和切片之间进行转换,从这个角度可以说它是一个OR ...

  7. 菜鸟Python学习笔记第一天:关于一些函数库的使用

    2017年1月3日 星期二 大一学习一门新的计算机语言真的很难,有时候连函数拼写出错查错都能查半天,没办法,谁让我英语太渣. 关于计算机语言的学习我想还是从C语言学习开始为好,Python有很多语言的 ...

  8. TinyWeb v1.0 正式完成第一个Release版本(功能基于 libuv 跨平台库)

    使用方法很简单,很容易融入现有项目,使现有项目拥有Web网站功能和WebSocket,以及Socket直连! 并且包含了一个跨平台(windows/linux)工具集合; 嗯,也挺棒的^,^ 在项目中 ...

  9. 在 Laravel 中使用图片处理库 Integration/Image

    系统需求 PHP >= 5.3 Fileinfo Extension GD Library (>=2.0) … or … Imagick PHP extension (>=6.5.7 ...

随机推荐

  1. Redis快速入门及实现

    redis的概念 (1)Redis的优点 以下是Redis的一些优点. 异常快 - Redis非常快,每秒可执行大约110000次的设置(SET)操作,每秒大约可执行81000次的读取/获取(GET) ...

  2. Tomcat工作原理解析!

    Tomcat简介   作者:杨晓(http://blog.sina.com.cn/u/1237288325) 一.Tomcat背景 自从JSP发布之后,推出了各式各样的JSP引擎.Apache Gro ...

  3. 基于Boost无锁队列实现的内存池

  4. POI1999(仓库管理员)

    题目链接:传送门

  5. 海康、大华NVR网络硬盘录像机录像无插件全平台访问实现—录像回放时间轴功能实现方法

    在之前的博文中我们有介绍方案*NVR硬件录像机web无插件播放方案(支持取特定时间段视频流)*:该片博文旨在介绍时间轴功能的实现和相关接口的调用: 时间轴样式展示: 问题分析 对于 时间轴的展示实现需 ...

  6. EasyNVR智能云终端硬件使用说明(EasyNVR无插件直播服务硬件的具体使用方法)

    问题背景 随着EasyNVR硬件版本(EasyNVR硬件云终端)的发布不少客户选择了EasyNVR云终端作为产品选择,在客户收到EasyNVR云终端的时候肯定都有一个疑问,那就是如何使用手头上的这个小 ...

  7. TFS二次开发-基线文件管理器(5)-源码文件的读取

      在上一节中,我们在保存标签之前,已经将勾选的文件路径保存到了Listbox中,这里只需要将保存的数据输出去为txt文档就可以做版本控制了.   版本文件比较复杂的是如何读取,也就是如何通过文件路径 ...

  8. Nginx敏感信息泄露漏洞(CVE-2017-7529)

    2017年7月11日,为了修复整数溢出漏洞(CVE-2017-7529), Nginx官方发布了nginx-1.12.1 stable和nginx-1.13.3 mainline版本,并且提供了官方p ...

  9. opencv如何打印长图?

    cv::Mat longMap(std::vector<cv::Mat> &set) { int matNumber = set.size(); int width = set[0 ...

  10. Hard模式学编程

    靖难: 我一直推崇一种学习编程的方法,就是learn programming the hard way,我把它翻译为Hard模式学编程 . 我觉得他有以下几个要领: 1. 一开始学习的时候,要尽量去化 ...