将行扫描到接口{}中不会自动将SQL类型转换为Go类型。相反,使用ColumnTypes方法将获得每列的数据类型,从而允许动态分配正确的Go类型。(以下内容未经测试,仅供参考。)
for i := range columns {
switch columnTypes[i].DatabaseTypeName() {
case "INT", "TINYINT", "SMALLINT", "MEDIUMINT", "BIGINT":
scanArgs[i] = new(int64)
default:
scanArgs[i] = new(string)
}
values[i] = scanArgs[i]
}
在脚本中:
package controllers
import (
"database/sql"
"encoding/json"
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
type RequestData struct {
FromData map[string]interface{} `json:"fromData"`
Call string `json:"Call"`
}
func HandleDatos(c *gin.Context) {
var requestData RequestData
if err := c.ShouldBindJSON(&requestData); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
fmt.Printf("Ejecutando procedimiento almacenado: CALL %s\n", requestData.Call)
fmt.Printf("Parámetros: %v\n", requestData.FromData)
var rows *sql.Rows
var err error
if len(requestData.FromData) > 0 {
query := "CALL " + requestData.Call + "("
params := []interface{}{}
for _, value := range requestData.FromData {
query += "?, "
params = append(params, value)
}
query = query[:len(query)-2] + ")"
rows, err = db.Raw(query, params...).Rows()
} else {
rows, err = db.Raw("CALL " + requestData.Call).Rows()
}
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
defer rows.Close()
result := make(map[string]interface{})
columns, err := rows.Columns()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
fmt.Printf("Columnas: %v\n", columns)
data := []map[string]interface{}{}
columnTypes, err := rows.ColumnTypes()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
for rows.Next() {
values := make([]interface{}, len(columns)
scanArgs := make([]interface{}, len(columns))
for i := range columns {
switch columnTypes[i].DatabaseTypeName() {
case "INT", "TINYINT", "SMALLINT", "MEDIUMINT", "BIGINT":
scanArgs[i] = new(int64)
default:
scanArgs[i] = new(string)
}
values[i] = scanArgs[i]
}
if err := rows.Scan(values...); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
fmt.Printf("Valores escaneados: %v\n", values)
row := make(map[string]interface{})
for i, col := range columns {
switch columnTypes[i].DatabaseTypeName() {
case "INT", "TINYINT", "SMALLINT", "MEDIUMINT", "BIGINT":
row[col] = *(scanArgs[i].(*int64))
default:
row[col] = *(scanArgs[i].(*string))
}
}
fmt.Printf("Fila escaneada: %v\n", row)
data = append(data, row)
}
fmt.Printf("Datos finales: %v\n", data)
if len(data) > 0 {
result["columns"] = columns
result["data"] = data
} else {
result["message"] = "Sin datos"
}
responseJSON, err := json.Marshal(result)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, string(responseJSON))
}
nb:您应该能够将此逻辑扩展到可能遇到的其他数据类型。