可以使用反射来实现根据PostgreSQL数据库表动态生成结构体。
首先需要连接到PostgreSQL数据库并查询表结构信息,可以使用”information_schema.columns”表来获取表名、列名、数据类型等信息:
db, err := sql.Open("postgres", "user=postgres password=123456 dbname=mydb sslmode=disable")
if err != nil {
log.Fatal(err)
}
defer db.Close()
rows, err := db.Query("SELECT table_name, column_name, data_type FROM information_schema.columns WHERE table_name = 'mytable'")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
接下来,可以通过遍历查询结果的方式动态生成结构体,并设置结构体的字段名和类型:
// 定义结构体类型
type MyTable struct {
Column1 string
Column2 int
Column3 float64
}
// 动态生成结构体
columns := make(map[string]string)
for rows.Next() {
var tableName, columnName, dataType string
if err := rows.Scan(&tableName, &columnName, &dataType); err != nil {
log.Fatal(err)
}
columns[columnName] = dataType
}
fields := make([]reflect.StructField, len(columns))
i := 0
for columnName, dataType := range columns {
// 根据数据类型设置结构体字段类型
var fieldType reflect.Type
switch dataType {
case "text":
fieldType = reflect.TypeOf("")
case "integer":
fieldType = reflect.TypeOf(0)
case "numeric":
fieldType = reflect.TypeOf(float64(0))
default:
log.Fatalf("unknown data type: %s", dataType)
}
fields[i] = reflect.StructField{
Name: strings.Title(columnName),
Type: fieldType,
}
i++
}
myTableType := reflect.StructOf(fields)
最后,可以使用反射创建一个新的结构体实例:
myTable := reflect.New(myTableType).Elem().Interface()
完整代码示例:
package main
import (
"database/sql"
"log"
"reflect"
"strings"
_ "github.com/lib/pq"
)
func main() {
db, err := sql.Open("postgres", "user=postgres password=123456 dbname=mydb sslmode=disable")
if err != nil {
log.Fatal(err)
}
defer db.Close()
rows, err := db.Query("SELECT table_name, column_name, data_type FROM information_schema.columns WHERE table_name = 'mytable'")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
columns := make(map[string]string)
for rows.Next() {
var tableName, columnName, dataType string
if err := rows.Scan(&tableName, &columnName, &dataType); err != nil {
log.Fatal(err)
}
columns[columnName] = dataType
}
fields := make([]reflect.StructField, len(columns))
i := 0
for columnName, dataType := range columns {
var fieldType reflect.Type
switch dataType {
case "text":
fieldType = reflect.TypeOf("")
case "integer":
fieldType = reflect.TypeOf(0)
case "numeric":
fieldType = reflect.TypeOf(float64(0))
default:
log.Fatalf("unknown data type: %s", dataType)
}
fields[i] = reflect.StructField{
Name: strings.Title(columnName),
Type: fieldType,
}
i++
}
myTableType := reflect.StructOf(fields)
myTable := reflect.New(myTableType).Elem().Interface()
log.Printf("%#v", myTable)
}