golang从SQL生成类型安全代码的插件库sqlc的使用

golang从SQL生成类型安全代码的插件库sqlc的使用

sqlc是一个从SQL生成类型安全代码的工具。它的工作原理如下:

  1. 你用SQL编写查询
  2. 运行sqlc生成这些查询的类型安全接口代码
  3. 编写调用生成代码的应用程序代码

基本使用示例

下面是一个完整的sqlc使用示例:

  1. 首先创建SQL文件 query.sql:
-- name: GetAuthor :one
SELECT * FROM authors
WHERE id = ? LIMIT 1;

-- name: ListAuthors :many
SELECT * FROM authors
ORDER BY name;

-- name: CreateAuthor :exec
INSERT INTO authors (
  name, bio
) VALUES (
  ?, ?
);

-- name: DeleteAuthor :exec
DELETE FROM authors
WHERE id = ?;
  1. 创建sqlc配置文件 sqlc.yaml:
version: "2"
sql:
  - engine: "mysql"
    schema: "schema.sql"
    queries: "query.sql"
    gen:
      go:
        package: "db"
        out: "db"
  1. 运行sqlc生成代码:
sqlc generate
  1. 生成的Go代码可以直接在应用中使用:
package main

import (
    "context"
    "database/sql"
    "fmt"
    "log"
    
    _ "github.com/go-sql-driver/mysql"
    "your-project/db"
)

func main() {
    // 初始化数据库连接
    dbConn, err := sql.Open("mysql", "user:password@/dbname")
    if err != nil {
        log.Fatal(err)
    }
    defer dbConn.Close()
    
    // 创建查询实例
    queries := db.New(dbConn)
    
    // 使用生成的查询方法
    ctx := context.Background()
    
    // 创建作者
    err = queries.CreateAuthor(ctx, db.CreateAuthorParams{
        Name: "John Doe",
        Bio:  sql.NullString{String: "Author of many books", Valid: true},
    })
    if err != nil {
        log.Fatal(err)
    }
    
    // 获取作者列表
    authors, err := queries.ListAuthors(ctx)
    if err != nil {
        log.Fatal(err)
    }
    
    for _, author := range authors {
        fmt.Printf("ID: %d, Name: %s\n", author.ID, author.Name)
    }
}

主要特点

  • 从SQL直接生成类型安全的Go代码
  • 支持多种数据库引擎(MySQL, PostgreSQL等)
  • 生成的代码完全类型安全,编译时检查SQL错误
  • 支持查询参数绑定和结果映射
  • 生成的代码干净简洁,易于使用

支持的查询类型

sqlc支持以下几种查询类型:

  • :one - 返回单行结果
  • :many - 返回多行结果
  • :exec - 执行但不返回结果
  • :execrows - 执行并返回影响的行数

安装

可以通过以下方式安装sqlc:

# 使用Homebrew(MacOS)
brew install sqlc

# 使用Go
go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest

# 使用Docker
docker pull sqlc/sqlc

sqlc是一个强大的工具,可以显著提高使用SQL时的开发效率和类型安全性,特别适合在Go项目中使用。


更多关于golang从SQL生成类型安全代码的插件库sqlc的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang从SQL生成类型安全代码的插件库sqlc的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用sqlc生成类型安全的Go代码

sqlc是一个强大的工具,可以从SQL查询生成类型安全的Go代码。它通过分析你的SQL模式(schema)和查询,自动生成对应的Go结构体和函数,避免了手动编写大量样板代码。

安装sqlc

首先需要安装sqlc:

go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest

或者使用Homebrew (macOS):

brew install sqlc

基本使用

1. 创建配置文件

在项目根目录创建sqlc.yaml配置文件:

version: "2"
sql:
  - engine: "postgresql"  # 也可以是mysql或sqlite
    queries: "query/"     # SQL查询文件目录
    schema: "schema/"     # SQL模式文件目录
    gen:
      go:
        package: "db"
        out: "db"
        sql_package: "pgx/v5"
        emit_json_tags: true
        emit_prepared_queries: true

2. 创建SQL模式文件

schema/目录下创建schema.sql:

CREATE TABLE authors (
  id   BIGSERIAL PRIMARY KEY,
  name text      NOT NULL,
  bio  text
);

CREATE TABLE books (
  id         BIGSERIAL PRIMARY KEY,
  author_id  BIGINT NOT NULL REFERENCES authors(id),
  title      text   NOT NULL,
  published  date   NOT NULL
);

3. 创建查询文件

query/目录下创建author.sql:

-- name: GetAuthor :one
SELECT * FROM authors
WHERE id = $1 LIMIT 1;

-- name: ListAuthors :many
SELECT * FROM authors
ORDER BY name;

-- name: CreateAuthor :one
INSERT INTO authors (
  name, bio
) VALUES (
  $1, $2
)
RETURNING *;

-- name: DeleteAuthor :exec
DELETE FROM authors
WHERE id = $1;

4. 生成代码

运行命令生成代码:

sqlc generate

这将在db/目录下生成Go代码。

生成的代码结构

sqlc会生成以下文件:

  • db.go - 数据库连接和查询器结构体
  • models.go - 数据库表对应的Go结构体
  • query/ - 每个SQL查询文件对应的Go代码

使用生成的代码

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/jackc/pgx/v5"
	"your-project/db"
)

func main() {
	conn, err := pgx.Connect(context.Background(), os.Getenv("DATABASE_URL"))
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close(context.Background())

	queries := db.New(conn)

	// 创建作者
	author, err := queries.CreateAuthor(context.Background(), db.CreateAuthorParams{
		Name: "J.R.R. Tolkien",
		Bio:  "Author of The Lord of the Rings",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Created author: %v\n", author)

	// 获取作者
	fetchedAuthor, err := queries.GetAuthor(context.Background(), author.ID)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Fetched author: %v\n", fetchedAuthor)

	// 列出所有作者
	authors, err := queries.ListAuthors(context.Background())
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("All authors:")
	for _, a := range authors {
		fmt.Printf("- %s\n", a.Name)
	}
}

高级特性

1. 自定义类型

可以在配置文件中指定类型映射:

overrides:
  - db_type: "uuid"
    go_type: "github.com/google/uuid.UUID"
  - db_type: "text"
    go_type: "github.com/lib/pq.StringArray"
    go_struct_tag: "json:\"-\""

2. 参数和结果结构体

sqlc会为每个查询生成参数和结果结构体。例如对于GetAuthor查询,会生成:

type GetAuthorParams struct {
	ID int64
}

type GetAuthorRow struct {
	ID   int64
	Name string
	Bio  sql.NullString
}

3. 事务支持

生成的代码天然支持事务:

tx, err := conn.Begin(context.Background())
if err != nil {
    log.Fatal(err)
}
defer tx.Rollback(context.Background())

qtx := queries.WithTx(tx)
// 使用qtx执行事务操作

最佳实践

  1. 将SQL查询组织到逻辑文件中
  2. 使用注释为查询添加文档
  3. 考虑将生成的代码提交到版本控制
  4. 在CI/CD流程中加入sqlc生成步骤
  5. 为复杂查询编写测试

sqlc通过将SQL直接转换为类型安全的Go代码,大大减少了数据库交互的样板代码,同时保持了SQL的灵活性和可读性。

回到顶部