Go与PostgreSQL:完整集成指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

为什么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}


更新和删除(Update

博客

书籍推荐