Golang PostgreSQL wrapper supporting chain calls, read-write separation, query builder, and complete connection management.
MySQL version here
Support read-write connection pool configuration, enabling pre-connections to improve efficiency.
Provide a chainable SQL query builder interface to prevent SQL injection attacks.
Complete support for create, read, update, and delete operations.
- Support for schemas
- ILIKE operator for case-insensitive pattern matching
- ON CONFLICT for upsert operations
- RETURNING clause for insert/update operations
go get github.com/pardnchiu/go-pg# default 127.0.0.1
PG_READ_HOST=
# default 5432
PG_READ_PORT=
# default postgres
PG_READ_USER=
# default empty
PG_READ_PASSWORD=
# default postgres
PG_READ_DATABASE=
# default disable
PG_READ_SSLMODE=
# default 4
PG_READ_CONNECTION=
# * default is read
PG_WRITE_HOST=
PG_WRITE_PORT=
PG_WRITE_USER=
PG_WRITE_PASSWORD=
PG_WRITE_DATABASE=
PG_WRITE_SSLMODE=
PG_WRITE_CONNECTION=config := goPg.Config{
Read: &goPg.DBConfig{
Host: "localhost",
Port: 5432,
User: "postgres",
Password: "password",
Database: "myapp",
SSLMode: "disable",
Connection: 10,
},
Write: &goPg.DBConfig{
Host: "localhost",
Port: 5432,
User: "postgres",
Password: "password",
Database: "myapp",
SSLMode: "disable",
Connection: 5,
},
}
pool, err := goPg.New(config)pool, err := goPg.New()rows, err := pool.Read.
Schema("public").
Table("users").
Select("id", "name", "email").
Where("status", "active").
Get()
defer rows.Close()
for rows.Next() {
var id int
var name, email string
rows.Scan(&id, &name, &email)
}rows, err := pool.Read.
Schema("public").
Table("users").
Select("*").
Where("age", ">", 18).
Where("status", "active").
Where("name", "ILIKE", "john"). // Case-insensitive
OrderBy("created_at", "DESC").
Limit(10).
Offset(20).
Get()rows, err := pool.Read.
Schema("public").
Table("users").
Select("users.name", "profiles.bio").
LeftJoin("profiles", "users.id", "profiles.user_id").
Where("users.status", "active").
Get()rows, err := pool.Read.
Schema("public").
Table("users").
Select("id", "name").
Where("status", "active").
Total().
Limit(10).
Get()
for rows.Next() {
var total, id int
var name string
rows.Scan(&total, &id, &name)
}data := map[string]interface{}{
"name": "Jane Doe",
"email": "[email protected]",
"age": 25,
}
lastID, err := pool.Write.
Schema("public").
Table("users").
Insert(data)updateData := map[string]interface{}{
"age": 26,
"status": "updated",
}
result, err := pool.Write.
Schema("public").
Table("users").
Where("id", 1).
Update(updateData)
rowsAffected, _ := result.RowsAffected()updateData := map[string]interface{}{
"updated_at": "NOW()",
"last_login": "CURRENT_TIMESTAMP",
}
result, err := pool.Write.
Schema("public").
Table("users").
Where("id", 1).
Update(updateData)result, err := pool.Write.
Schema("public").
Table("users").
Where("id", 1).
Increase("view_count", 1).
Update()data := map[string]interface{}{
"email": "[email protected]",
"name": "New User",
"age": 30,
}
// Update all fields on conflict
lastID, err := pool.Write.
Schema("public").
Table("users").
Upsert(data, []string{"email"})data := map[string]interface{}{
"email": "[email protected]",
"name": "New User",
}
updateData := map[string]interface{}{
"name": "Updated User",
"last_login": "NOW()",
}
lastID, err := pool.Write.
Schema("public").
Table("users").
Upsert(data, []string{"email"}, updateData)rows, err := pool.Read.Query(
"SELECT * FROM users WHERE age > $1 AND status = $2",
18,
"active",
)result, err := pool.Write.Exec(
"UPDATE users SET status = $1 WHERE age > $2",
"senior",
35,
)NOW()CURRENT_TIMESTAMPCURRENT_DATECURRENT_TIMELOCALTIMESTAMPLOCALTIMETRANSACTION_TIMESTAMP()STATEMENT_TIMESTAMP()CLOCK_TIMESTAMP()GEN_RANDOM_UUID()RANDOM()- And more...
defer pool.Close()The package automatically listens for SIGINT and SIGTERM signals for graceful shutdown.
Queries taking longer than 20ms are automatically logged.
package main
import (
"log"
goPg "github.com/pardnchiu/go-pg"
)
func main() {
pool, err := goPg.New()
if err != nil {
log.Fatal(err)
}
defer pool.Close()
// Insert
data := map[string]interface{}{
"name": "John Doe",
"email": "[email protected]",
"age": 30,
}
lastID, _ := pool.Write.Schema("public").Table("users").Insert(data)
// Query
rows, _ := pool.Read.
Schema("public").
Table("users").
Select("id", "name", "email").
Where("age", ">", 18).
OrderBy("created_at", "DESC").
Limit(10).
Get()
defer rows.Close()
for rows.Next() {
var id int
var name, email string
rows.Scan(&id, &name, &email)
log.Printf("User: %s (%s)\n", name, email)
}
// Update
updateData := map[string]interface{}{
"age": 31,
}
pool.Write.Schema("public").Table("users").Where("id", lastID).Update(updateData)
}This project is licensed under the MIT license.
©️ 2025 邱敬幃 Pardn Chiu