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 %s\n", requestData.Call)
fmt.Printf("Parámetros: %v\n", 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: %v\n", 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: %v\n", 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: %v\n", row) // Punto de impresión
// Agrega esta fila al resultado
data = append(data, values)
}
fmt.Printf("Datos finales: %v\n", 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 %s\n", requestData.Call)
fmt.Printf("Parámetros: %v\n", 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: %v\n", 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: %v\n", 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: %v\n", row) // Punto de impresión
// Agrega esta fila al resultado
data = append(data, row)
}
fmt.Printf("Datos finales: %v\n", 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:您應該能夠針對可能遇到的其他數據類型擴展此邏輯。






