Golang使用row.Scan扫描多行结果报错:sql: expected 1 arguments, got 2
问题原因及解决方法
核心问题点
错误使用
QueryRow处理多行结果QueryRow仅用于查询单行数据,你的存储过程返回多行结果,用它会导致只读取第一行,且因为结果集有2列,但你传入的是一个切片指针(仅1个参数),触发expected 1 arguments, got 2的参数不匹配错误。直接扫描到切片的方式不合法
Scan()要求传入与结果集列数一一对应的变量指针,不能直接把切片指针传进去,切片需要逐行读取结构体后再填充。
修正后的代码
type Permission struct { ID int `json:"id"` Name string `json:"name"` Description string `json:"description"` ParentResourceID int `json:"parentResourceId"` } func GetResourcesByResourceTypeId(resourceTypeId string) ([]Permission, string, error) { db, ctx := db.GetDB() query := "CALL usp_GetParentResourceListByResourceTypeID(?)" var resourceList []Permission stmt, err := db.Prepare(query) if err != nil { log.Errorln("Error in preparing statement. " + err.Error()) return nil, "Error in preparing statement.", err } defer stmt.Close() // 使用Query获取多行结果集,替代QueryRow rows, err := stmt.Query(ctx, resourceTypeId) if err != nil { log.Errorln("Error executing query. " + err.Error()) return nil, "Error executing query.", err } defer rows.Close() // 循环遍历每一行数据 for rows.Next() { var p Permission // 存储过程仅返回ID和Name两个字段,对应扫描这两个变量 err = rows.Scan(&p.ID, &p.Name) if err != nil { log.Errorln("Error scanning row. " + err.Error()) return nil, "Error scanning row.", err } // 结构体中未返回的字段手动设置默认值(可根据业务调整) p.Description = "" p.ParentResourceID = 0 resourceList = append(resourceList, p) } // 检查遍历过程中是否出现错误 if err = rows.Err(); err != nil { log.Errorln("Row iteration error. " + err.Error()) return nil, "Row iteration error.", err } if len(resourceList) == 0 { log.Warningln("Resource retrieval failed, ResourceTypeID: " + resourceTypeId + ".") return resourceList, "Resource retrieval failed.", nil } return resourceList, "Resource retrieval.", nil }
额外说明
- 你的
Permission结构体有4个字段,但存储过程仅返回ID和Name,扫描时必须严格对应返回的列数,未返回的字段需要手动设置默认值或按业务逻辑处理。 - 必须调用
rows.Close()释放数据库资源,用defer确保即使执行出错也能正常释放。 - 循环结束后要检查
rows.Err(),捕获遍历过程中可能出现的隐性错误。
内容的提问来源于stack exchange,提问作者Harsha W
相关产品推荐
相关产品推荐

