go-pg/pg
GitHub: go-pg/pg
Go 语言的 PostgreSQL 客户端与 ORM 库,专注于充分利用 PostgreSQL 特性并优化性能(现已进入维护模式,后续开发转向 Bun)。
Stars: 5782 | Forks: 413
# Golang 的 PostgreSQL 客户端和 ORM
## 维护模式
go-pg 处于维护模式,仅处理关键问题。新的开发工作在
[**Bun**](https://bun.uptrace.dev/guide/pg-migration.html) 仓库中进行,它提供类似的功能,
并且支持 PostgreSQL、MySQL、MariaDB 和 SQLite。
## [Golang ORM](https://github.com/uptrace/bun)
[](https://github.com/go-pg/pg/actions/workflows/build.yml)
[](https://pkg.go.dev/github.com/go-pg/pg/v10)
[](https://pg.uptrace.dev/)
[](https://discord.gg/rWtp5Aj)
- [文档](https://pg.uptrace.dev)
- [参考](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc)
- [示例](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#pkg-examples)
- 示例项目:
- [monetr](https://github.com/monetr/monetr) - 一款专注于规划
周期性开支的预算应用程序
- [bunrouter](https://github.com/go-bun/bun-realworld-app)
- [gin](https://github.com/gogjango/gjango)
- [go-kit](https://github.com/Tsovak/rest-api-demo)
- [aah framework](https://github.com/kieusonlam/golamapi)
## 教程
- [YouTube 上的 GraphQL 教程](https://www.youtube.com/playlist?list=PLzQWIQOqeUSNwXcneWYJHUREAIucJ5UZn)。
- [使用 Golang、PostgreSQL 和 Docker 的现代 API 设计](https://bognov.tech/modern-api-design-with-golang-postgresql-and-docker)
## 生态系统
- 由 [vmihailenco](https://github.com/go-pg/migrations) 和
[robinjoseph08](https://github.com/robinjoseph08/go-pg-migrations) 提供的 Migrations。
- [Genna - 用于生成 go-pg 模型的 CLI 工具](https://github.com/dizzyfool/genna)。
- [bigint](https://github.com/d-fal/bigint) - 用于 go-pg 的 big.Int 类型。
- [urlstruct](https://github.com/go-pg/urlstruct) 用于将 `url.Values` 解码到 structs 中。
- [Sharding](https://github.com/go-pg/sharding)。
- [go-pg-monitor](https://github.com/hypnoglow/go-pg-monitor) - 基于 go-pg
客户端统计信息的 Prometheus 指标。
## 功能
- 基本类型: integers、floats、string、bool、time.Time、net.IP、net.IPNet。
- sql.NullBool、sql.NullString、sql.NullInt64、sql.NullFloat64 和
[pg.NullTime](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#NullTime)。
- [sql.Scanner](http://golang.org/pkg/database/sql/#Scanner) 和
[sql/driver.Valuer](http://golang.org/pkg/database/sql/driver/#Valuer) 接口。
- structs、maps 和 arrays 默认被序列化为 JSON。
- 使用
[array tag](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB-Model-PostgresArrayStructTag)
和 [Array wrapper](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-Array) 支持 PostgreSQL 多维数组。
- 使用
[hstore tag](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB-Model-HstoreStructTag)
和 [Hstore wrapper](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-Hstore) 支持 Hstore。
- [Composite types](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB-Model-CompositeType)。
- 默认情况下,所有 struct 字段都是 nullable 的,且零值(空字符串、0、zero time、空 map
或 slice、nil ptr)会被序列化为 SQL `NULL`。`pg:",notnull"` 用于添加 SQL `NOT NULL`
约束,而 `pg:",use_zero"` 用于允许 Go 的零值。
- [Transactions](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB-Begin)。
- [Prepared statements](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB-Prepare)。
- 使用
`LISTEN` 和 `NOTIFY` 实现[通知](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-Listener)。
- 使用
`COPY FROM` 和 `COPY TO` [复制数据](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB-CopyFrom)。
- 使用
context.Context 实现[超时](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#Options)和取消查询。
- 支持
[circuit breaker](https://en.wikipedia.org/wiki/Circuit_breaker_design_pattern) 的自动连接池。
- 遇到网络错误时自动重试查询。
- 使用
[ORM](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model) 和
[SQL](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Query) 操作模型。
- 使用
[ORM](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-SelectSomeColumnsIntoVars)
和 [SQL](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-Scan) 扫描变量。
- 使用
on-conflict 的 [SelectOrInsert](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-InsertSelectOrInsert)。
- 使用
ORM 的 [INSERT ... ON CONFLICT DO UPDATE](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-InsertOnConflictDoUpdate)。
- 批量/批次
[inserts](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-BulkInsert)、
[updates](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-BulkUpdate) 和
[deletes](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-BulkDelete)。
- 使用
[WITH](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-SelectWith) 和
[WrapWith](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-SelectWrapWith) 的公共表表达式。
- 使用
`EXPLAIN` 的 [CountEstimate](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-CountEstimate)
来获取[预估的匹配行数](https://wiki.postgresql.org/wiki/Count_estimate)。
- ORM 支持
[has one](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-HasOne)、
[belongs to](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-BelongsTo)、
[has many](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-HasMany) 和
[many to many](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-ManyToMany)
,并支持复合/多列主键。
- [Soft deletes](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-SoftDelete)。
- [从 structs 创建表](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-CreateTable)。
- [ForEach](https://pkg.go.dev/github.com/go-pg/pg/v10?tab=doc#example-DB.Model-ForEach),它为
查询返回的每一行调用一个函数,而无需将所有行加载到内存中。
## 安装说明
go-pg 支持最新的 2 个 Go 版本,并且需要支持
[modules](https://github.com/golang/go/wiki/Modules) 的 Go 版本。因此,请确保初始化一个 Go
模块:
```
go mod init github.com/my/repo
```
然后安装 go-pg(注意导入中的 _v10_;省略它是一个常见的错误):
```
go get github.com/go-pg/pg/v10
```
## 快速开始
```
package pg_test
import (
"fmt"
"github.com/go-pg/pg/v10"
"github.com/go-pg/pg/v10/orm"
)
type User struct {
Id int64
Name string
Emails []string
}
func (u User) String() string {
return fmt.Sprintf("User<%d %s %v>", u.Id, u.Name, u.Emails)
}
type Story struct {
Id int64
Title string
AuthorId int64
Author *User `pg:"rel:has-one"`
}
func (s Story) String() string {
return fmt.Sprintf("Story<%d %s %s>", s.Id, s.Title, s.Author)
}
func ExampleDB_Model() {
db := pg.Connect(&pg.Options{
User: "postgres",
})
defer db.Close()
err := createSchema(db)
if err != nil {
panic(err)
}
user1 := &User{
Name: "admin",
Emails: []string{"admin1@admin", "admin2@admin"},
}
_, err = db.Model(user1).Insert()
if err != nil {
panic(err)
}
_, err = db.Model(&User{
Name: "root",
Emails: []string{"root1@root", "root2@root"},
}).Insert()
if err != nil {
panic(err)
}
story1 := &Story{
Title: "Cool story",
AuthorId: user1.Id,
}
_, err = db.Model(story1).Insert()
if err != nil {
panic(err)
}
// Select user by primary key.
user := &User{Id: user1.Id}
err = db.Model(user).WherePK().Select()
if err != nil {
panic(err)
}
// Select all users.
var users []User
err = db.Model(&users).Select()
if err != nil {
panic(err)
}
// Select story and associated author in one query.
story := new(Story)
err = db.Model(story).
Relation("Author").
Where("story.id = ?", story1.Id).
Select()
if err != nil {
panic(err)
}
fmt.Println(user)
fmt.Println(users)
fmt.Println(story)
// Output: User<1 admin [admin1@admin admin2@admin]>
// [User<1 admin [admin1@admin admin2@admin]> User<2 root [root1@root root2@root]>]
// Story<1 Cool story User<1 admin [admin1@admin admin2@admin]>>
}
// createSchema creates database schema for User and Story models.
func createSchema(db *pg.DB) error {
models := []interface{}{
(*User)(nil),
(*Story)(nil),
}
for _, model := range models {
err := db.Model(model).CreateTable(&orm.CreateTableOptions{
Temp: true,
})
if err != nil {
return err
}
}
return nil
}
```
## 另请参阅
- [Golang PostgreSQL](https://bun.uptrace.dev/postgres/)
- [Golang HTTP router](https://github.com/uptrace/bunrouter)
- [Golang ClickHouse ORM](https://github.com/uptrace/go-clickhouse)
- [Golang msgpack](https://github.com/vmihailenco/msgpack)
- [分布式追踪工具](https://get.uptrace.dev/compare/distributed-tracing-tools.html)
标签:EVTX分析, Golang, ORM, PostgreSQL, SOC Prime, 安全编程, 开发工具, 数据库驱动, 日志审计, 测试用例