为什么Go和PostgreSQL是理想组合?
在后端开发世界中,Go(或Golang)和PostgreSQL已被证明是构建高负载、可靠系统的强大组合。Go为我们带来了令人难以置信的性能、简洁性和出色的并发支持,而PostgreSQL则是一款功能丰富、可靠且可扩展的企业级数据库。将两者结合,您将获得一个能够承受初创公司负载和企业级项目要求的技术栈。
在本文中,我们不仅会快速浏览语法。我们将创建一份完整的实践指南:从安装驱动程序到优化连接池和处理事务。您将学习如何避免常见错误,并编写高效的Go代码来操作PostgreSQL。让我们开始吧!
入门:选择驱动程序并建立连接
首先需要做的是安装驱动程序。在Go世界中,有两个主要候选者:
- lib/pq — 经典、简单,但已不再积极维护。
- pgx — 现代、快速、积极开发,支持更多PostgreSQL功能(例如COPY、LISTEN/NOTIFY、数组)。我推荐使用它。
安装pgx:
go get github.com/jackc/pgx/v5现在编写代码连接到数据库。创建文件main.go:
package main
import ( "context" "fmt" "log"
"github.com/jackc/pgx/v5/pgxpool")
func main() { // 连接URL:用户、密码、主机、端口、数据库名 dsn := "postgres://myuser:mypassword@localhost:5432/mydb?sslmode=disable"
// 创建连接池 pool, err := pgxpool.New(context.Background(), dsn) if err != nil { log.Fatalf("无法创建连接池:%v", err) } defer pool.Close()
// 测试连接 err = pool.Ping(context.Background()) if err != nil { log.Fatalf("无法连接:%v", err) }
fmt.Println("成功连接到PostgreSQL!")}请注意:我们使用的是pgxpool,而不是简单连接。连接池是生产环境的必备品。它允许重复使用连接,避免创建和关闭连接的开销。
CRUD操作:创建、读取、更新和删除
现在让我们对users表实现经典操作。假设我们有如下结构体:
type User struct { ID int Name string Age int}创建表(Create)
最好使用单独的工具执行迁移,但为了示例,我将展示如何执行原始SQL:
func createTable(ctx context.Context, pool *pgxpool.Pool) error { query := ` CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, name TEXT NOT NULL, age INT NOT NULL ); ` _, err := pool.Exec(ctx, query) return err}插入记录(Insert)
使用QueryRow返回生成的ID:
func createUser(ctx context.Context, pool *pgxpool.Pool, user *User) error { query := `INSERT INTO users (name, age) VALUES ($1, $2) RETURNING id` err := pool.QueryRow(ctx, query, user.Name, user.Age).Scan(&user.ID) return err}读取记录(Select)
func getUserByID(ctx context.Context, pool *pgxpool.Pool, id int) (*User, error) { query := `SELECT id, name, age FROM users WHERE id = $1` user := &User{} err := pool.QueryRow(ctx, query, id).Scan(&user.ID, &user.Name, &user.Age) if err != nil { return nil, err } return user, nil}