You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Golang+SQLC将PostgreSQL IN查询转为变量并通过结构体传递

问题概述

在使用Golang结合sqlc工具将PostgreSQL查询转为带变量的代码时,遇到类型不匹配问题:

  • 原查询中fos."name" IN ('IT & Software', 'Analisis Data & Statistik')替换为变量$2后,sqlc生成的参数类型为string,但实际需要接收Golang结构体SearchMajorReq中FieldOfStudies []string类型的数组参数(对应JSON请求体中的数组字段),导致类型错误。

原查询语句:

SELECT
    mou."id",
    mou."name",
    mou.description,
    mou.img_url,
    um.favorite 
FROM
    majors_of_universities mou
    JOIN field_of_studies fos ON mou.field_of_studies_id = fos."id"
    JOIN univ_major um ON mou."id" = um.majors_of_universities_id 
WHERE
    mou."name" ILIKE '%%' 
    AND fos."name" IN ( 'IT & Software', 'Analisis Data & Statistik' ) 
ORDER BY
    mou."name" 
    LIMIT 99 OFFSET 0;

用户修改后的变量化查询(存在类型问题):

SELECT
    mou."id",
    mou."name",
    mou.description,
    mou.img_url,
    um.favorite 
FROM
    majors_of_universities mou
    JOIN field_of_studies fos ON mou.field_of_studies_id = fos."id"
    JOIN univ_major um ON mou."id" = um.majors_of_universities_id 
WHERE
    mou."name" ILIKE $1 
    AND fos."name" IN ($2) 
ORDER BY
    mou."name" 
    LIMIT $3 OFFSET $4;

Golang结构体定义:

type SearchMajorReq struct {
    Name           string   `json:"name"`
    FieldOfStudies []string `json:"field_of_studies"`
    Limit          int32    `json:"limit"`
    Page           int32    `json:"page"`
}

期望接收的JSON请求体:

{
    "name":"",
    "field_of_studies": ["1", "2", "3"],
    "limit": 10,
    "page": 1
}
解决方法

1. 修改SQL查询的IN子句为ANY语法

PostgreSQL支持使用= ANY($2)接收数组参数,sqlc会自动将其映射为Golang的[]string类型。修改后的SQL需添加sqlc必要注释:

-- name: SearchMajors :many
SELECT
    mou."id",
    mou."name",
    mou.description,
    mou.img_url,
    um.favorite 
FROM
    majors_of_universities mou
    JOIN field_of_studies fos ON mou.field_of_studies_id = fos."id"
    JOIN univ_major um ON mou."id" = um.majors_of_universities_id 
WHERE
    mou."name" ILIKE $1 
    AND fos."name" = ANY($2) 
ORDER BY
    mou."name" 
    LIMIT $3 OFFSET $4;

2. 处理分页参数转换

请求体中的page从1开始,需计算OFFSET值:offset = (page - 1) * limit,在Golang代码中完成计算后传入sqlc生成的函数。

3. Golang调用示例

// 解析请求体到SearchMajorReq
var req SearchMajorReq
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
    // 处理解析错误
}

// 处理空数组场景(避免PostgreSQL报错,可根据业务调整)
if len(req.FieldOfStudies) == 0 {
    req.FieldOfStudies = []string{""}
}

// 计算分页偏移量
offset := (req.Page - 1) * req.Limit

// 调用sqlc生成的查询函数
majors, err := db.SearchMajors(ctx, db.SearchMajorsParams{
    Name:           "%" + req.Name + "%", // 补全LIKE通配符
    FieldOfStudies: req.FieldOfStudies,
    Limit:          req.Limit,
    Offset:         offset,
})
if err != nil {
    // 处理查询错误
}

4. 验证参数类型

sqlc生成的SearchMajorsParams结构体中,FieldOfStudies会自动匹配为[]string类型,与SearchMajorReq的字段完全兼容,解决类型不匹配问题。

内容的提问来源于stack exchange,提问作者Adhitya Resadikara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 20:18:33