golang简化PostgreSQL查询与结果处理的插件库pigpgxscan的使用
golang简化PostgreSQL查询与结果处理的插件库pigpgxscan的使用
pigpgxscan是一个简单的pgx包装器,用于执行和扫描查询结果。
特性
- 一体化工具
- 简单的事务管理:
- 可以设置
idle_in_transaction_session_timeout
本地选项 - 可以设置
statement_timeout
本地选项
- 可以设置
使用示例
执行查询
package main
import (
"context"
"log"
"github.com/alexeyco/pig"
"github.com/jackc/pgx/v4"
)
func main() {
// 连接PostgreSQL数据库
conn, err := pgx.Connect(context.Background(), "")
if err != nil {
log.Fatalln(err)
}
// 创建pig实例
p := pig.New(conn)
// 执行DELETE查询
affectedRows, err := p.Query().Exec("DELETE FROM things WHERE id = $1", 123)
if err != nil {
log.Fatalln(err)
}
log.Println("affected", affectedRows, "rows")
}
获取单个实体
package main
import (
"context"
"log"
"github.com/alexeyco/pig"
"github.com/jackc/pgx/v4"
)
func main() {
// 连接PostgreSQL数据库
conn, err := pgx.Connect(context.Background(), "")
if err != nil {
log.Fatalln(err)
}
// 创建pig实例
p := pig.New(conn)
// 查询单个值
var cnt int64
err = p.Query().Get(&cnt, "SELECT count(*) FROM things")
if err != nil {
log.Fatalln(err)
}
log.Println(cnt, "things found")
}
查询多个实体
package main
import (
"context"
"log"
"github.com/alexeyco/pig"
"github.com/jackc/pgx/v4"
)
// 定义Thing结构体,映射数据库表
type Thing struct {
ID int64 `db:"id"`
Name string `db:"name"`
Quantity int64 `db:"quantity"`
}
func main() {
// 连接PostgreSQL数据库
conn, err := pgx.Connect(context.Background(), "")
if err != nil {
log.Fatalln(err)
}
// 创建pig实例
p := pig.New(conn)
// 查询多个Thing对象
var things []Thing
err = p.Query().Select(&things, "SELECT * FROM things")
if err != nil {
log.Fatalln(err)
}
log.Println(things)
}
执行事务
package main
import (
"context"
"log"
"time"
"github.com/alexeyco/pig"
"github.com/jackc/pgx/v4"
)
func main() {
// 连接PostgreSQL数据库
conn, err := pgx.Connect(context.Background(), "")
if err != nil {
log.Fatalln(err)
}
// 创建pig实例
p := pig.New(conn)
// 执行事务,设置超时时间为1秒
var affectedRows int64
err = p.Tx(pig.TransactionTimeout(time.Second)).
Exec(func(ex *pig.Ex) error {
affectedRows, err = p.Query().Exec("DELETE FROM things WHERE id = $1", 123)
if err != nil {
return err
}
return nil
})
if err != nil {
log.Fatalln(err)
}
log.Println("affected", affectedRows, "rows")
}
许可证
MIT License
Copyright © 2021 Alexey Popov
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
更多关于golang简化PostgreSQL查询与结果处理的插件库pigpgxscan的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang简化PostgreSQL查询与结果处理的插件库pigpgxscan的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
pigpgxscan - 简化PostgreSQL查询与结果处理的Golang库
pigpgxscan 是一个基于 pgx 的轻量级 Golang 库,旨在简化 PostgreSQL 数据库查询和结果映射到结构体的过程。它提供了比标准 pgx 更简洁的 API,减少了样板代码。
主要特性
- 自动将查询结果映射到结构体
- 支持命名参数查询
- 简化事务管理
- 支持批量操作
- 轻量级设计,无额外依赖
安装
go get github.com/roderm/pigpgxscan
基本用法
初始化连接
import (
"context"
"github.com/jackc/pgx/v5/pgxpool"
"github.com/roderm/pigpgxscan"
)
func main() {
ctx := context.Background()
// 创建pgx连接池
pool, err := pgxpool.New(ctx, "postgres://user:password@localhost:5432/dbname")
if err != nil {
panic(err)
}
defer pool.Close()
// 创建pigpgxscan扫描器
scanner := pigpgxscan.NewScanner(pool)
}
查询单条记录
type User struct {
ID int `db:"id"`
Name string `db:"name"`
Email string `db:"email"`
CreatedAt time.Time `db:"created_at"`
}
func getUser(ctx context.Context, scanner *pigpgxscan.Scanner, userID int) (*User, error) {
var user User
err := scanner.Get(ctx, &user, "SELECT * FROM users WHERE id = $1", userID)
if err != nil {
return nil, err
}
return &user, nil
}
查询多条记录
func getUsers(ctx context.Context, scanner *pigpgxscan.Scanner) ([]User, error) {
var users []User
err := scanner.Select(ctx, &users, "SELECT * FROM users WHERE active = true ORDER BY created_at DESC")
if err != nil {
return nil, err
}
return users, nil
}
使用命名参数
func searchUsers(ctx context.Context, scanner *pigpgxscan.Scanner, name string, email string) ([]User, error) {
var users []User
err := scanner.Select(ctx, &users, `
SELECT * FROM users
WHERE name LIKE :name AND email LIKE :email
ORDER BY created_at DESC`,
pigpgxscan.NamedArgs{
"name": "%" + name + "%",
"email": "%" + email + "%",
})
if err != nil {
return nil, err
}
return users, nil
}
执行更新操作
func updateUser(ctx context.Context, scanner *pigpgxscan.Scanner, user *User) error {
_, err := scanner.Exec(ctx, `
UPDATE users
SET name = $1, email = $2
WHERE id = $3`,
user.Name, user.Email, user.ID)
return err
}
使用事务
func transferFunds(ctx context.Context, scanner *pigpgxscan.Scanner, from, to int, amount float64) error {
// 开始事务
tx, err := scanner.Begin(ctx)
if err != nil {
return err
}
defer tx.Rollback(ctx) // 确保事务总是回滚,除非明确提交
// 执行转账操作
_, err = tx.Exec(ctx, "UPDATE accounts SET balance = balance - $1 WHERE id = $2", amount, from)
if err != nil {
return err
}
_, err = tx.Exec(ctx, "UPDATE accounts SET balance = balance + $1 WHERE id = $2", amount, to)
if err != nil {
return err
}
// 提交事务
return tx.Commit(ctx)
}
高级功能
批量插入
func batchInsertUsers(ctx context.Context, scanner *pigpgxscan.Scanner, users []User) error {
_, err := scanner.BulkInsert(ctx, "users", users)
return err
}
自定义类型处理
type Status string
const (
StatusActive Status = "active"
StatusInactive Status = "inactive"
)
type UserWithStatus struct {
ID int `db:"id"`
Name string `db:"name"`
Status Status `db:"status"`
}
// 注册自定义类型扫描器
func init() {
pigpgxscan.RegisterTypeScanner(func(src interface{}) (interface{}, error) {
switch v := src.(type) {
case string:
return Status(v), nil
case []byte:
return Status(string(v)), nil
default:
return nil, fmt.Errorf("unsupported type for Status: %T", src)
}
}, Status(""))
}
性能考虑
pigpgxscan 在性能上做了以下优化:
- 使用 pgx 原生连接池
- 减少反射使用,缓存反射结果
- 最小化内存分配
- 支持预编译语句
与标准 pgx 对比
相比直接使用 pgx,pigpgxscan 提供了:
- 更简洁的 API
- 自动结构体映射
- 命名参数支持
- 更简单的事务管理
- 批量操作支持
总结
pigpgxscan 是一个实用的轻量级库,特别适合需要频繁与 PostgreSQL 交互的中小型项目。它通过简化常见操作减少了样板代码,同时保持了良好的性能。对于更复杂的查询或需要精细控制的情况,可以直接使用底层的 pgx 功能。
完整的文档和更多示例可以参考项目的 GitHub 仓库:https://github.com/roderm/pigpgxscan