Go SQL驱动程序获取interface{}列值

huangapple go评论81阅读模式
英文:

Go SQL driver get interface{} column values

问题

我正在尝试使用Go SQL驱动程序从数据库表中读取数据,并将值转换为[]map[string]interface{}。映射的键是列名,值是interface{}类型。我将所有的列都添加到一个数组中。我正在使用https://github.com/go-sql-driver/mysql/wiki/Examples中的"RawBytes"代码示例作为起点。

然而,在该示例中,所有的列值都被转换为string,如下所示:

// 获取行数据
for rows.Next() {
// 从数据中获取RawBytes
err = rows.Scan(scanArgs...)
if err != nil {
panic(err.Error()) // 在你的应用程序中使用适当的错误处理,而不是panic
}

// 现在对数据进行一些操作。
// 这里我们只是将每一列作为字符串打印出来。
var value string
for i, col := range values {
    // 在这里我们可以检查值是否为nil(NULL值)
    if col == nil {
        value = "NULL"
    } else {
        value = string(col) // 注意:在这里转换为字符串
    }
    fmt.Println(columns[i], ": ", value)
}
fmt.Println("-----------------------------------")

}

有没有办法保留它作为interface{},这样我就可以在使用[]map[string]interface{}中的列时进行必要的类型转换呢?

英文:

I am trying to use go sql driver to read from database tables and I am converting the values to []map[string]interface{}. The column name is the key of the map and the values are of interface{}. I am adding all the columns into an array. I am using the code sample for "RawBytes" at https://github.com/go-sql-driver/mysql/wiki/Examples as an example to start with.

However, in the example -all the column values are converted to string as follows,

// Fetch rows
for rows.Next() {
    // get RawBytes from data
    err = rows.Scan(scanArgs...)
    if err != nil {
        panic(err.Error()) // proper error handling instead of panic in your app
    }

    // Now do something with the data.
    // Here we just print each column as a string.
    var value string
    for i, col := range values {
        // Here we can check if the value is nil (NULL value)
        if col == nil {
            value = "NULL"
        } else {
            value = string(col) //ATTN : converted to string here
        }
        fmt.Println(columns[i], ": ", value)
    }
    fmt.Println("-----------------------------------")
}

Is there a way to retain it as interface{} so I can do the necessary type casting while using the columns from []map[string]interface{}

答案1

得分: 3

参考这个答案,你可以像这样做:

var myMap = make(map[string]interface{})
rows, err := db.Query("SELECT * FROM myTable")
defer rows.Close()
if err != nil {
    log.Fatal(err)
}
colNames, err := rows.Columns()
if err != nil {
    log.Fatal(err)
}
cols := make([]interface{}, len(colNames))
colPtrs := make([]interface{}, len(colNames))
for i := 0; i < len(colNames); i++ {
    colPtrs[i] = &cols[i]
}
for rows.Next() {
    err = rows.Scan(colPtrs...)
    if err != nil {
        log.Fatal(err)
    }
    for i, col := range cols {
        myMap[colNames[i]] = col
    }
    // 使用map进行操作
    for key, val := range myMap {
        fmt.Println("Key:", key, "Value Type:", reflect.TypeOf(val))
    }
}

使用reflect包你可以根据需要获取每列的类型就像最后的循环示例一样

这是通用的方法适用于任何表格任意列数等情况

<details>
<summary>英文:</summary>

See [this https://stackoverflow.com/questions/20271123/go-lang-sql-in-parameters][1] answer which my answer is based on. Using that you can do something like this:

    var myMap = make(map[string]interface{})
	rows, err := db.Query(&quot;SELECT * FROM myTable&quot;)
	defer rows.Close()
	if err != nil {
		log.Fatal(err)
	}
	colNames, err := rows.Columns()
	if err != nil {
		log.Fatal(err)
	}
	cols := make([]interface{}, len(colNames))
	colPtrs := make([]interface{}, len(colNames))
	for i := 0; i &lt; len(colNames); i++ {
		colPtrs[i] = &amp;cols[i]
	}
	for rows.Next() {
		err = rows.Scan(colPtrs...)
        if err != nil {
            log.Fatal(err)
        }
		for i, col := range cols {
			myMap[colNames[i]] = col
		}
        // Do something with the map
	    for key, val := range myMap {
		    fmt.Println(&quot;Key:&quot;, key, &quot;Value Type:&quot;, reflect.TypeOf(val))
	    }
	}

Using the reflect package you can then get the Type for each column as needed as demonstrated with the loop at the end.

This is generic and will work with any table, number of columns etc.

  [1]: https://stackoverflow.com/questions/20271123/go-lang-sql-in-parameters

</details>



# 答案2
**得分**: 0

在经过长时间的努力后我找到了解决方案请检查下面的函数它将sql.RawBytes转换为Int64这可以很容易地修改以适应任何数据类型

```go
func GetInt64ColumnValue(payload sql.RawBytes) (int64, error) {
    content := reflect.ValueOf(payload).Interface().(sql.RawBytes) // 转换为字节
    data := string(content) // 转换为字符串
    i, err := strconv.ParseInt(data, 10, 64) // 转换为int或您首选的数据类型

    if err != nil {
        log.Printf("将%s转换为int时出错:%s", data, err.Error())
        return 0, err
    }

    return i, nil
}
英文:

AFter a long struggle i found out the solution. Check belowfunction that converts sql.RawBytes to Int64. This can be easily altered to fit any data type

func GetInt64ColumnValue(payload sql.RawBytes) (int64, error) {
content := reflect.ValueOf(payload).Interface().(sql.RawBytes) // convert to bytes
data := string(content) //convert to string  
i, err := strconv.ParseInt(data,10,64)  // convert to int or your preferred data type
if err != nil {
log.Printf(&quot;got error converting %s to int error %s &quot;,data,err.Error())
return 0, err
}
return i, nil

}

huangapple
  • 本文由 发表于 2015年3月17日 23:10:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/29102725.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定