如何将 struct 类型转换为 []interface{} 以便用于 pgx.CopyFromSlice 函数?

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

How to convert struct-Type into []interface{} for pgx.CopyFromSlice

问题

将数据复制到Postgres数据库时,我将所有数据收集到一个切片中,然后将其传递给pgx.CopyFromCopyFrom需要一个CopyFromSource,可以使用CopyFromSlice来实现,其中需要传递一个函数,该函数需要返回给定索引的数据的函数。下面是我的GetAsInterface函数。

目前,我通过逐个列出所有结构体成员来实现。是否有更方便和更简洁的方法?毕竟,序列是相同的。

我的想法是稍后将列名作为注释添加到我的MbpImport类型中,以便有一个更易于维护的代码。当前,我必须两次列出成员,一次在定义类型时,一次在将其转换为[]interface{}时。我还必须在另一个函数中跟踪返回数据库列名的函数,以确保它们具有正确的顺序。我希望注释能够帮助我,因为注释将随着结构体的每次更改而移动。

  1. type MbpImport struct {
  2. Partner_id int
  3. Target_table string
  4. Keystring string
  5. Info_date time.Time
  6. Mbp string
  7. Mbp_id int
  8. Client_id string
  9. Status string
  10. Spam_traps int64
  11. Spam_traps_imp bool
  12. Email_volume int64
  13. Spam_clicks int64
  14. Spam_clicks_imp bool
  15. Inbox int64
  16. Spam_filter int64
  17. Spam_filter_imp bool
  18. Dkim_missing int64
  19. Dkim_errors int64
  20. Dkim_imp bool
  21. Dkim_simple_strict int64
  22. Dkim_simple_relaxed int64
  23. }
  24. type MbpImportRows struct {
  25. index map[string]map[string]map[string]int
  26. rows []MbpImport
  27. }
  28. func (data *MbpImportRows) GetAsInterface(index int) ([]interface{}, error) {
  29. return []interface{}{
  30. data.rows[index].Partner_id,
  31. data.rows[index].Target_table,
  32. data.rows[index].Keystring,
  33. data.rows[index].Info_date,
  34. data.rows[index].Mbp,
  35. data.rows[index].Mbp_id,
  36. data.rows[index].Client_id,
  37. data.rows[index].Status,
  38. data.rows[index].Spam_traps,
  39. data.rows[index].Spam_traps_imp,
  40. data.rows[index].Email_volume,
  41. data.rows[index].Spam_clicks,
  42. data.rows[index].Spam_clicks_imp,
  43. data.rows[index].Inbox,
  44. data.rows[index].Spam_filter,
  45. data.rows[index].Spam_filter_imp,
  46. data.rows[index].Dkim_missing,
  47. data.rows[index].Dkim_errors,
  48. data.rows[index].Dkim_imp,
  49. data.rows[index].Dkim_simple_strict,
  50. data.rows[index].Dkim_simple_relaxed,
  51. },
  52. nil
  53. }
英文:

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.

  1. type MbpImport struct {
  2. Partner_id int
  3. Target_table string
  4. Keystring string
  5. Info_date time.Time
  6. Mbp string
  7. Mbp_id int
  8. Client_id string
  9. Status string
  10. Spam_traps int64
  11. Spam_traps_imp bool
  12. Email_volume int64
  13. Spam_clicks int64
  14. Spam_clicks_imp bool
  15. Inbox int64
  16. Spam_filter int64
  17. Spam_filter_imp bool
  18. Dkim_missing int64
  19. Dkim_errors int64
  20. Dkim_imp bool
  21. Dkim_simple_strict int64
  22. Dkim_simple_relaxed int64
  23. }
  24. type MbpImportRows struct {
  25. index map[string]map[string]map[string]int
  26. rows []MbpImport
  27. }
  28. func (data *MbpImportRows) GetAsInterface(index int) ([]interface{}, error) {
  29. return []interface{}{
  30. data.rows[index].Partner_id,
  31. data.rows[index].Target_table,
  32. data.rows[index].Keystring,
  33. data.rows[index].Info_date,
  34. data.rows[index].Mbp,
  35. data.rows[index].Mbp_id,
  36. data.rows[index].Client_id,
  37. data.rows[index].Status,
  38. data.rows[index].Spam_traps,
  39. data.rows[index].Spam_traps_imp,
  40. data.rows[index].Email_volume,
  41. data.rows[index].Spam_clicks,
  42. data.rows[index].Spam_clicks_imp,
  43. data.rows[index].Inbox,
  44. data.rows[index].Spam_filter,
  45. data.rows[index].Spam_filter_imp,
  46. data.rows[index].Dkim_missing,
  47. data.rows[index].Dkim_errors,
  48. data.rows[index].Dkim_imp,
  49. data.rows[index].Dkim_simple_strict,
  50. data.rows[index].Dkim_simple_relaxed,
  51. },
  52. nil
  53. }

答案1

得分: 1

我按照@mkopriva的评论并使用反射进行了以下更改:

  1. type MbpImport struct {
  2. Partner_id int `dbcol:"partner_id"`
  3. Target_table string `dbcol:"target_table"`
  4. Keystring string `dbcol:"keystring"`
  5. Info_date time.Time `dbcol:"info_date"`
  6. Mbp string `dbcol:"mbp"`
  7. Mbp_id int `dbcol:"mbp_id"`
  8. Client_id string `dbcol:"client_id"`
  9. Status string `dbcol:"status"`
  10. Spam_traps int64 `dbcol:"spam_traps"`
  11. Spam_traps_imp bool `dbcol:"spam_traps_imp"`
  12. Email_volume int64 `dbcol:"email_volume"`
  13. Spam_clicks int64 `dbcol:"spam_clicks"`
  14. Spam_clicks_imp bool `dbcol:"spam_clicks_imp"`
  15. Inbox int64 `dbcol:"inbox"`
  16. Spam_filter int64 `dbcol:"spam_filter"`
  17. Spam_filter_imp bool `dbcol:"spam_filter_imp"`
  18. Dkim_missing int64 `dbcol:"dkim_missing"`
  19. Dkim_errors int64 `dbcol:"dkim_errors"`
  20. Dkim_imp bool `dbcol:"dkim_imp"`
  21. Dkim_simple_strict int64 `dbcol:"dkim_simple_strict"`
  22. Dkim_simple_relaxed int64 `dbcol:"dkim_simple_relaxed"`
  23. }
  24. func (data *MbpImportRows) Columns() []string {
  25. s := reflect.ValueOf(new(MbpImport)).Elem()
  26. myStr := make([]string, s.NumField())
  27. for i := 0; i < s.NumField(); i++ {
  28. myStr[i] = s.Type().Field(i).Tag.Get("dbcol")
  29. }
  30. return myStr
  31. }
  32. func (data *MbpImportRows) GetAsInterface(index int) ([]interface{}, error) {
  33. s := reflect.ValueOf(&data.rows[index]).Elem()
  34. result := make([]interface{}, s.NumField())
  35. for i := 0; i < s.NumField(); i++ {
  36. result[i] = s.Field(i).Interface()
  37. }
  38. return result, nil
  39. }
英文:

I followed the comment of @mkopriva and use reflect:

  1. type MbpImport struct {
  2. Partner_id int `dbcol:&quot;partner_id&quot;`
  3. Target_table string `dbcol:&quot;target_table&quot;`
  4. Keystring string `dbcol:&quot;keystring&quot;`
  5. Info_date time.Time `dbcol:&quot;info_date&quot;`
  6. Mbp string `dbcol:&quot;mbp&quot;`
  7. Mbp_id int `dbcol:&quot;mbp_id&quot;`
  8. Client_id string `dbcol:&quot;client_id&quot;`
  9. Status string `dbcol:&quot;status&quot;`
  10. Spam_traps int64 `dbcol:&quot;spam_traps&quot;`
  11. Spam_traps_imp bool `dbcol:&quot;spam_traps_imp&quot;`
  12. Email_volume int64 `dbcol:&quot;email_volume&quot;`
  13. Spam_clicks int64 `dbcol:&quot;spam_clicks&quot;`
  14. Spam_clicks_imp bool `dbcol:&quot;spam_clicks_imp&quot;`
  15. Inbox int64 `dbcol:&quot;inbox&quot;`
  16. Spam_filter int64 `dbcol:&quot;spam_filter&quot;`
  17. Spam_filter_imp bool `dbcol:&quot;spam_filter_imp&quot;`
  18. Dkim_missing int64 `dbcol:&quot;dkim_missing&quot;`
  19. Dkim_errors int64 `dbcol:&quot;dkim_errors&quot;`
  20. Dkim_imp bool `dbcol:&quot;dkim_imp&quot;`
  21. Dkim_simple_strict int64 `dbcol:&quot;dkim_simple_strict&quot;`
  22. Dkim_simple_relaxed int64 `dbcol:&quot;dkim_simple_relaxed&quot;`
  23. }
  24. func (data *MbpImportRows) Columns() []string {
  25. s := reflect.ValueOf(new(MbpImport)).Elem()
  26. myStr := make([]string, s.NumField())
  27. for i := 0; i &lt; s.NumField(); i++ {
  28. myStr[i] = s.Type().Field(i).Tag.Get(&quot;dbcol&quot;)
  29. }
  30. return myStr
  31. }
  32. func (data *MbpImportRows) GetAsInterface(index int) ([]interface{}, error) {
  33. s := reflect.ValueOf(&amp;data.rows[index]).Elem()
  34. result := make([]interface{}, s.NumField())
  35. for i := 0; i &lt; s.NumField(); i++ {
  36. result[i] = s.Field(i).Interface()
  37. }
  38. return result, nil
  39. }

huangapple
  • 本文由 发表于 2023年4月26日 20:26:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76110711.html
匿名

发表评论

匿名网友

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

确定