Golang用struct值填充函数参数

时间:2018-05-27 18:54:23

标签: sql go reflection

我想知道是否有一种方法可以在golang中使用结构的所有值(通常是不同类型的值)填充可变参数函数参数。

我想到的具体示例是以下代码段,使用https://github.com/DATA-DOG/go-sqlmock为模拟的postgres数据库查询生成一行:

rows := sqlmock.NewRows([]string{
        "id",
        "updated_at",
        "created_at",
        "meta",
        "account_id",
        "currency",
        "nickname",
        "scheme_name",
        "identification",
        "name",
        "identification_secondary",
        "servicer_scheme_name",
        "servicer_identification",
        "institution_id",
        "client_id",
    }).AddRow(
        mock.Values.AccountID,
        time.Now(),
        time.Now(),
        "{}",
        "12345678",
        "GBP",
        "Test",
        "Schema",
        "12345676534263",
        "New account",
        "12345",
        "schema",
        "test id",
        mock.Values.InstitutionID,
        mock.Values.ClientID,
    )

鉴于参数总是表示结构(字段和值),我试图使用结构来填充字段和值,而不是手动完成每个。使用反射字段相当简单,但是值为多种类型,AddRow函数定义为:

AddRow func(values ...driver.Value) *Rows

有没有办法循环结构字段并提供类型化值来实现类似?...

account := Account{
        ID:             "ABCD12436364",
        UpdatedAt:      time.Now(),
        CreatedAt:      time.Now(),
        Meta:           "{}",
        AccountID:      "12345678",
        Currency:       "GBP",
        Nickname:       "Test",
        SchemeName:     "Scheme",
        Identification: "12345676534263",
        Name:           "New account",
        IdentificationSecondary: "12345",
        ServicerSchemeName:      "scheme",
        ServicerIdentification:  "test id",
        InstitutionID:           "ABCD123456",
        ClientID:                "ZXCVB12436",
    }

rows := sqlmock.NewRows(account.GetFieldsJSON()).AddRow(account.GetValues())

1 个答案:

答案 0 :(得分:2)

这可以使用reflect包来完成,它允许你循环结构的字段,然后构造一个driver.Value的片段。然后,您将结果切片传递给AddRow,并使用尾随...来“解压缩”内容。

var result []driver.Value

rv := reflect.ValueOf(account)
for i := 0; i < rv.NumField(); i++ {
    fv := rv.Field(i)
    dv := driver.Value(fv.Interface())
    result = append(result, dv)
}

AddRow(result...)

请注意,在这种情况下,转化driver.Value(fv.Interface())有效,因为driver.Value是一个空接口,fv.Interface()返回的类型也是如此。

https://play.golang.org/p/7Oy8_YrmkMa