英文:
How to convert struct-Type into []interface{} for pgx.CopyFromSlice
问题
将数据复制到Postgres数据库时,我将所有数据收集到一个切片中,然后将其传递给pgx.CopyFrom
。CopyFrom
需要一个CopyFromSource
,可以使用CopyFromSlice
来实现,其中需要传递一个函数,该函数需要返回给定索引的数据的函数。下面是我的GetAsInterface
函数。
目前,我通过逐个列出所有结构体成员来实现。是否有更方便和更简洁的方法?毕竟,序列是相同的。
我的想法是稍后将列名作为注释添加到我的MbpImport
类型中,以便有一个更易于维护的代码。当前,我必须两次列出成员,一次在定义类型时,一次在将其转换为[]interface{}
时。我还必须在另一个函数中跟踪返回数据库列名的函数,以确保它们具有正确的顺序。我希望注释能够帮助我,因为注释将随着结构体的每次更改而移动。
type MbpImport struct {
Partner_id int
Target_table string
Keystring string
Info_date time.Time
Mbp string
Mbp_id int
Client_id string
Status string
Spam_traps int64
Spam_traps_imp bool
Email_volume int64
Spam_clicks int64
Spam_clicks_imp bool
Inbox int64
Spam_filter int64
Spam_filter_imp bool
Dkim_missing int64
Dkim_errors int64
Dkim_imp bool
Dkim_simple_strict int64
Dkim_simple_relaxed int64
}
type MbpImportRows struct {
index map[string]map[string]map[string]int
rows []MbpImport
}
func (data *MbpImportRows) GetAsInterface(index int) ([]interface{}, error) {
return []interface{}{
data.rows[index].Partner_id,
data.rows[index].Target_table,
data.rows[index].Keystring,
data.rows[index].Info_date,
data.rows[index].Mbp,
data.rows[index].Mbp_id,
data.rows[index].Client_id,
data.rows[index].Status,
data.rows[index].Spam_traps,
data.rows[index].Spam_traps_imp,
data.rows[index].Email_volume,
data.rows[index].Spam_clicks,
data.rows[index].Spam_clicks_imp,
data.rows[index].Inbox,
data.rows[index].Spam_filter,
data.rows[index].Spam_filter_imp,
data.rows[index].Dkim_missing,
data.rows[index].Dkim_errors,
data.rows[index].Dkim_imp,
data.rows[index].Dkim_simple_strict,
data.rows[index].Dkim_simple_relaxed,
},
nil
}
英文:
For copying data into a Postgres database, I collect all my data in a slice, which I then hand over to pgx.CopyFrom
. CopyFrom
requires a CopyFromSource
which can be achieved with CopyFromSlice
to which you have to pass a function which needs a function that returns for a given index the data of that "row". That's my GetAsInterface
function below.
Currently I do it by listing all my struct's members, one after the other. Is there a more convenient and less verbose way? The sequence is identical after all.
My idea is to later have the column names as annotation to my MbpImport
type in order to have a more maintainable code. Curently I have to list the members two times, once when defining the type and a second time when converting it to []interface{}
. I also have to keep track in another function, which returns the database column names, that those have the correct sequence. I hope an annotation will help me here as the annotation will move with every change in the struct.
type MbpImport struct {
Partner_id int
Target_table string
Keystring string
Info_date time.Time
Mbp string
Mbp_id int
Client_id string
Status string
Spam_traps int64
Spam_traps_imp bool
Email_volume int64
Spam_clicks int64
Spam_clicks_imp bool
Inbox int64
Spam_filter int64
Spam_filter_imp bool
Dkim_missing int64
Dkim_errors int64
Dkim_imp bool
Dkim_simple_strict int64
Dkim_simple_relaxed int64
}
type MbpImportRows struct {
index map[string]map[string]map[string]int
rows []MbpImport
}
func (data *MbpImportRows) GetAsInterface(index int) ([]interface{}, error) {
return []interface{}{
data.rows[index].Partner_id,
data.rows[index].Target_table,
data.rows[index].Keystring,
data.rows[index].Info_date,
data.rows[index].Mbp,
data.rows[index].Mbp_id,
data.rows[index].Client_id,
data.rows[index].Status,
data.rows[index].Spam_traps,
data.rows[index].Spam_traps_imp,
data.rows[index].Email_volume,
data.rows[index].Spam_clicks,
data.rows[index].Spam_clicks_imp,
data.rows[index].Inbox,
data.rows[index].Spam_filter,
data.rows[index].Spam_filter_imp,
data.rows[index].Dkim_missing,
data.rows[index].Dkim_errors,
data.rows[index].Dkim_imp,
data.rows[index].Dkim_simple_strict,
data.rows[index].Dkim_simple_relaxed,
},
nil
}
答案1
得分: 1
我按照@mkopriva的评论并使用反射进行了以下更改:
type MbpImport struct {
Partner_id int `dbcol:"partner_id"`
Target_table string `dbcol:"target_table"`
Keystring string `dbcol:"keystring"`
Info_date time.Time `dbcol:"info_date"`
Mbp string `dbcol:"mbp"`
Mbp_id int `dbcol:"mbp_id"`
Client_id string `dbcol:"client_id"`
Status string `dbcol:"status"`
Spam_traps int64 `dbcol:"spam_traps"`
Spam_traps_imp bool `dbcol:"spam_traps_imp"`
Email_volume int64 `dbcol:"email_volume"`
Spam_clicks int64 `dbcol:"spam_clicks"`
Spam_clicks_imp bool `dbcol:"spam_clicks_imp"`
Inbox int64 `dbcol:"inbox"`
Spam_filter int64 `dbcol:"spam_filter"`
Spam_filter_imp bool `dbcol:"spam_filter_imp"`
Dkim_missing int64 `dbcol:"dkim_missing"`
Dkim_errors int64 `dbcol:"dkim_errors"`
Dkim_imp bool `dbcol:"dkim_imp"`
Dkim_simple_strict int64 `dbcol:"dkim_simple_strict"`
Dkim_simple_relaxed int64 `dbcol:"dkim_simple_relaxed"`
}
func (data *MbpImportRows) Columns() []string {
s := reflect.ValueOf(new(MbpImport)).Elem()
myStr := make([]string, s.NumField())
for i := 0; i < s.NumField(); i++ {
myStr[i] = s.Type().Field(i).Tag.Get("dbcol")
}
return myStr
}
func (data *MbpImportRows) GetAsInterface(index int) ([]interface{}, error) {
s := reflect.ValueOf(&data.rows[index]).Elem()
result := make([]interface{}, s.NumField())
for i := 0; i < s.NumField(); i++ {
result[i] = s.Field(i).Interface()
}
return result, nil
}
英文:
I followed the comment of @mkopriva and use reflect:
type MbpImport struct {
Partner_id int `dbcol:"partner_id"`
Target_table string `dbcol:"target_table"`
Keystring string `dbcol:"keystring"`
Info_date time.Time `dbcol:"info_date"`
Mbp string `dbcol:"mbp"`
Mbp_id int `dbcol:"mbp_id"`
Client_id string `dbcol:"client_id"`
Status string `dbcol:"status"`
Spam_traps int64 `dbcol:"spam_traps"`
Spam_traps_imp bool `dbcol:"spam_traps_imp"`
Email_volume int64 `dbcol:"email_volume"`
Spam_clicks int64 `dbcol:"spam_clicks"`
Spam_clicks_imp bool `dbcol:"spam_clicks_imp"`
Inbox int64 `dbcol:"inbox"`
Spam_filter int64 `dbcol:"spam_filter"`
Spam_filter_imp bool `dbcol:"spam_filter_imp"`
Dkim_missing int64 `dbcol:"dkim_missing"`
Dkim_errors int64 `dbcol:"dkim_errors"`
Dkim_imp bool `dbcol:"dkim_imp"`
Dkim_simple_strict int64 `dbcol:"dkim_simple_strict"`
Dkim_simple_relaxed int64 `dbcol:"dkim_simple_relaxed"`
}
func (data *MbpImportRows) Columns() []string {
s := reflect.ValueOf(new(MbpImport)).Elem()
myStr := make([]string, s.NumField())
for i := 0; i < s.NumField(); i++ {
myStr[i] = s.Type().Field(i).Tag.Get("dbcol")
}
return myStr
}
func (data *MbpImportRows) GetAsInterface(index int) ([]interface{}, error) {
s := reflect.ValueOf(&data.rows[index]).Elem()
result := make([]interface{}, s.NumField())
for i := 0; i < s.NumField(); i++ {
result[i] = s.Field(i).Interface()
}
return result, nil
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论