你的
rows
类型需要为
[][]interface{}
,即每行是列值列表的行列表。然后用那种类型的每一个
row
可以“打开”到
Exec
呼叫使用
...
.
即:
for _, row := range rows {
_, err = stmt.Exec(row...)
}
从
[]model.User
或
[]model.Whatever
到
[]接口
你需要使用反射。如果需要,还可以使用反射来获取列名和表名。
假设您的模型类型如下:
type User struct {
_ struct{} `rel:"users"`
Username string `col:"username"`
Age int `col:"age"`
}
现在可以使用反射从字段的结构标记中获取表名和列列表。(注意使用
_
(空白)字段只是如何指定表名的一个选项,它有其优点和缺点,因此由您来选择,这里我只是演示如何利用反射包)。
下面是一个更完整的示例,说明如何从标记收集“meta”数据,以及如何从结构字段聚合列值。
func DBBulkInsert(source interface{}) {
slice := reflect.ValueOf(source)
if slice.Kind() != reflect.Slice {
panic("not a slice")
}
elem := slice.Type().Elem()
if elem.Kind() == reflect.Ptr {
elem = elem.Elem()
}
if elem.Kind() != reflect.Struct {
panic("slice elem not a struct, nor a pointer to a struct")
}
// get table and column names
var tableName string
var cols []string
for i := 0; i < elem.NumField(); i++ {
f := elem.Field(i)
if rel := f.Tag.Get("rel"); len(rel) > 0 {
tableName = rel
}
if col := f.Tag.Get("col"); len(col) > 0 {
cols = append(cols, col)
}
}
// aggregate rows
rows := [][]interface{}{}
for i := 0; i < slice.Len(); i++ {
m := slice.Index(i)
if m.Kind() == reflect.Ptr {
m = m.Elem()
}
vals := []interface{}{}
for j := 0; j < m.NumField(); j++ {
ft := m.Type().Field(j)
if col := ft.Tag.Get("col"); len(col) > 0 {
f := m.Field(j)
vals = append(vals, f.Interface())
}
}
rows = append(rows, vals)
}
// ...
}
Run it on playground