【问题标题】:Golang populate function parameters with struct valuesGolang 使用结构值填充函数参数
【发布时间】:2018-11-06 09:42:05
【问题描述】:

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

我正在考虑的具体示例是以下 sn-p 使用 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())

【问题讨论】:

    标签: sql go reflection


    【解决方案1】:

    这可以通过reflect 包来完成,它允许您遍历结构的字段,然后构造driver.Values 的切片。然后,您可以将生成的切片传递给 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-20
      • 1970-01-01
      • 2011-04-30
      • 1970-01-01
      • 2011-03-28
      • 1970-01-01
      • 1970-01-01
      • 2016-12-28
      相关资源
      最近更新 更多