与其使用根据数据字段的数量、容量和字段类型预先定义的struct
,不如使用可扩展且可以包含多种数据类型作为值的map
,这将更加有利。例如,在数据库端,更改表中的列名、列类型或列数不会影响与查询数据库相关的go代码,例如go数据结构您将从数据库查询返回rows
。
是否有方法在golang sql包或相关驱动程序中知道数据的类型,在行中,由数据库查询返回,以定义具有适当数量的字段和类型的struct
?
如果没有,map
如何使用返回的rows
的列名键和行字段值来完成此map
?
要做到这一点,您必须使用具有interface{}
类型值的映射,以便它们可以存储任何类型。如果还需要列名,则必须使用rows.Columns()
来提取所有数据和类型。
这将从表中读取所有列,并以interface{}
类型将值存储在map中,并将列名作为键。在此基础上,你应该能够找出你需要什么来使用。
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
}
// Do something with the map
for key, val := range myMap {
fmt.Println("Key:", key, "Value Type:", reflect.TypeOf(val))
}
}
使用反射包,您可以根据需要获得每个列的Type,正如最后的循环所演示的那样。或者您可以使用类型开关来提取类型。
以上是通用的,可以处理任意数量的列和类型。