Golang中database/sql包存在的代码缺陷问题
Golang中database/sql包存在的代码缺陷问题 go 版本:go 1.19
我的问题出在 database/sql 包上。服务中已有可用的 plsql 代码。值是通过 map 发送到服务的。但数量没有限制,
我需要通过 sql.Named 发送给 db.exec(),我尝试用循环和接口来检查,但都没有成功。
请帮帮我。
我的代码如下:
在控制器中
const begin = `
jsonData.Put('stateid', :stateid);
`
array_for_param := map[string]string{
"stateid": "a",
}
temp, err := services.Perform(c, begin, array_for_param, i_User_Id)
if err != nil {
log.Fatal(err)
}
服务代码:
var params []interface{}
for key, value := range array_for_param {
params = append(params, sql.Named(key, value))
}
if _, err := db.Exec(declare+begin+end,
sql.Named("i_User_Id", i_User_Id),
params...,
); err != nil {
log.Fatal(err)
}
); err != nil {
log.Fatal(err)
}
我遇到的主要问题是,我需要使用一个 for 循环来发送 sql.Named 代码,而循环次数是未知的
if _, err := db.Exec(declare+begin+end,
sql.Named("i_User_Id", i_User_Id),
for key, value := range array_for_param {
return sql.Named(key, value)
}
); err != nil {
log.Fatal(err)
}
我也尝试过这样做
更多关于Golang中database/sql包存在的代码缺陷问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于Golang中database/sql包存在的代码缺陷问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在 database/sql 包中,使用 sql.Named 参数时,需要将参数展开为切片。你的问题在于如何动态构建命名参数列表。以下是修正后的代码示例:
服务层代码修正:
func Perform(c context.Context, sqlStr string, params map[string]string, userID int) error {
// 构建命名参数切片
namedParams := make([]interface{}, 0, len(params)+1)
// 添加固定参数
namedParams = append(namedParams, sql.Named("i_User_Id", userID))
// 动态添加map中的参数
for key, value := range params {
namedParams = append(namedParams, sql.Named(key, value))
}
// 执行SQL
_, err := db.Exec(sqlStr, namedParams...)
if err != nil {
return err
}
return nil
}
控制器层调用示例:
const sqlStr = `
DECLARE
jsonData JSON_OBJECT_T := JSON_OBJECT_T();
BEGIN
jsonData.PUT('stateid', :stateid);
-- 其他PL/SQL逻辑
END;
`
params := map[string]string{
"stateid": "a",
"other_param": "value", // 可以动态添加更多参数
}
err := services.Perform(c, sqlStr, params, userID)
if err != nil {
log.Fatal(err)
}
关键点说明:
namedParams切片需要预分配容量以提高性能:make([]interface{}, 0, len(params)+1)- 使用切片展开操作符
...传递参数:db.Exec(sqlStr, namedParams...) - 可以混合固定参数和动态参数,顺序不影响,因为使用的是命名参数
更通用的解决方案(支持不同类型参数):
func PerformDynamic(c context.Context, sqlStr string, dynamicParams map[string]interface{}, fixedParams map[string]interface{}) error {
namedParams := make([]interface{}, 0, len(dynamicParams)+len(fixedParams))
// 添加固定参数
for key, value := range fixedParams {
namedParams = append(namedParams, sql.Named(key, value))
}
// 添加动态参数
for key, value := range dynamicParams {
namedParams = append(namedParams, sql.Named(key, value))
}
_, err := db.Exec(sqlStr, namedParams...)
return err
}
这样处理可以支持任意数量的命名参数,且参数类型可以是 interface{} 以适应不同的数据类型需求。

