从 MySQL/Go 表获取行数据

2024年 2月 14日 35.5k 0

从 mysql/go 表获取行数据

php小编小新在这篇文章中将向大家介绍如何从MySQL/Go表获取行数据。MySQL是一种流行的关系型数据库管理系统,而Go是一种强大的开发语言。在开发过程中,我们经常需要从数据库中获取数据并进行处理。本文将详细介绍如何使用Go语言连接MySQL数据库,并通过查询语句从表中获取行数据。无论您是初学者还是有经验的开发者,本文都将为您提供有用的指导和示例代码。让我们开始吧!

问题内容

首先它读取代码,以便您了解它的逻辑,当运行我捕获它的存储过程时,它会为我带来一个包含我必须返回的数据的表,列的名称确实会带来它对我来说,但列的数据没有给我带来任何东西,我无法创建模型,并且存储过程的响应有 n 个列,有 n 个不同的名称,但列的不同之处在于具有 int 数据和字符串数据,我需要您从列中捕获正确的数据,因为一切正常,但列中的数据却不起作用:

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 %sn", requestData.Call)
fmt.Printf("Parámetros: %vn", requestData.FromData)

var rows *sql.Rows
var err error

// Verifica si FromData contiene valores
if len(requestData.FromData) > 0 {
// Si hay valores en FromData, crea una consulta con parámetros
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 {
// Si no hay valores en FromData, ejecuta el procedimiento almacenado sin parámetros
rows, err = db.Raw("CALL " + requestData.Call).Rows()
}

if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
defer rows.Close()

// Convierte los resultados en un mapa
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: %vn", columns) // Punto de impresión

data := [][]interface{}{} // Almacena los datos de filas
for rows.Next() {
values := make([]interface{}, len(columns))
for i := range columns {
values[i] = new(interface{})
}

if err := rows.Scan(values...); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

fmt.Printf("Valores escaneados: %vn", values) // Punto de impresión

row := make(map[string]interface{})
for i, col := range columns {
val := *(values[i].(*interface{}))
row[col] = val
}

fmt.Printf("Fila escaneada: %vn", row) // Punto de impresión

// Agrega esta fila al resultado
data = append(data, values)
}

fmt.Printf("Datos finales: %vn", data) // Punto de impresión

if len(data) > 0 {
result["columns"] = columns
result["data"] = data
} else {
// Si no hay datos, establece un mensaje personalizado
result["message"] = "Sin datos"
}

// Convierte el resultado en JSON y devuelve la respuesta
responseJSON, err := json.Marshal(result)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

c.JSON(http.StatusOK, string(responseJSON))
}

登录后复制

这就是它返回给我的内容,其中显示“columns”:[“idPunto”,“nombre”]该部分没问题,但包含数据的行不是我所期望的:

解决方法

将行扫描到接口{}中不会自动将 SQL 类型转换为 Go 类型。相反,使用 ColumnTypes 方法将获取每列的数据类型,允许您动态分配正确的 Go 类型。 (以下内容未经测试,仅供参考。)例如

for i := range columns {
// Use the column types to determine the appropriate scan type
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 %sn", requestData.Call)
fmt.Printf("Parámetros: %vn", requestData.FromData)

var rows *sql.Rows
var err error

// Verifica si FromData contiene valores
if len(requestData.FromData) > 0 {
// Si hay valores en FromData, crea una consulta con parámetros
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 {
// Si no hay valores en FromData, ejecuta el procedimiento almacenado sin parámetros
rows, err = db.Raw("CALL " + requestData.Call).Rows()
}

if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
defer rows.Close()

// Convierte los resultados en un mapa
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: %vn", columns) // Punto de impresión

data := []map[string]interface{}{} // Almacena los datos de filas

// Get the column types
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 {
// Use the column types to determine the appropriate scan type
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: %vn", values) // Punto de impresión

row := make(map[string]interface{})
for i, col := range columns {
// Cast the scanned values to the appropriate data types
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: %vn", row) // Punto de impresión

// Agrega esta fila al resultado
data = append(data, row)
}

fmt.Printf("Datos finales: %vn", data) // Punto de impresión

if len(data) > 0 {
result["columns"] = columns
result["data"] = data
} else {
// Si no hay datos, establece un mensaje personalizado
result["message"] = "Sin datos"
}

// Convierte el resultado en JSON y devuelve la respuesta
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:您应该能够针对可能遇到的其他数据类型扩展此逻辑。

以上就是从 MySQL/Go 表获取行数据的详细内容,更多请关注每日运维网(www.mryunwei.com)其它相关文章!

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论