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:您應該能夠針對可能遇到的其他數據類型擴展此邏輯。