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

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

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

问题

将数据复制到Postgres数据库时,我将所有数据收集到一个切片中,然后将其传递给pgx.CopyFromCopyFrom需要一个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:&quot;partner_id&quot;`
    Target_table         string     `dbcol:&quot;target_table&quot;`
    Keystring            string     `dbcol:&quot;keystring&quot;`
    Info_date            time.Time  `dbcol:&quot;info_date&quot;`
    Mbp                  string     `dbcol:&quot;mbp&quot;`
    Mbp_id               int        `dbcol:&quot;mbp_id&quot;`
    Client_id            string     `dbcol:&quot;client_id&quot;`
    Status               string     `dbcol:&quot;status&quot;`
    Spam_traps           int64      `dbcol:&quot;spam_traps&quot;`
    Spam_traps_imp       bool       `dbcol:&quot;spam_traps_imp&quot;`
    Email_volume         int64      `dbcol:&quot;email_volume&quot;`
    Spam_clicks          int64      `dbcol:&quot;spam_clicks&quot;`
    Spam_clicks_imp      bool       `dbcol:&quot;spam_clicks_imp&quot;`
    Inbox                int64      `dbcol:&quot;inbox&quot;`
    Spam_filter          int64      `dbcol:&quot;spam_filter&quot;`
    Spam_filter_imp      bool       `dbcol:&quot;spam_filter_imp&quot;`
    Dkim_missing         int64      `dbcol:&quot;dkim_missing&quot;`
    Dkim_errors          int64      `dbcol:&quot;dkim_errors&quot;`
    Dkim_imp             bool       `dbcol:&quot;dkim_imp&quot;`
    Dkim_simple_strict   int64      `dbcol:&quot;dkim_simple_strict&quot;`
    Dkim_simple_relaxed  int64      `dbcol:&quot;dkim_simple_relaxed&quot;`
}

func (data *MbpImportRows) Columns() []string {
    s := reflect.ValueOf(new(MbpImport)).Elem()
    myStr := make([]string, s.NumField())
    for i := 0; i &lt; s.NumField(); i++ {
        myStr[i] = s.Type().Field(i).Tag.Get(&quot;dbcol&quot;)
    }
    return myStr
}

func (data *MbpImportRows) GetAsInterface(index int) ([]interface{}, error) {
    s := reflect.ValueOf(&amp;data.rows[index]).Elem()
    result := make([]interface{}, s.NumField())
    for i := 0; i &lt; s.NumField(); i++ {
        result[i] = s.Field(i).Interface()
    }
    return result, nil
}

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:

确定