I'm wondering is there is a way to populate a variadic function parameter in golang with all the values of a struct (which will typically be of varying types).
The specific example I'm thinking of is the following snippet to generate a row for a mocked postgres database query using https://github.com/DATA-DOG/go-sqlmock :
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,
)
Given the parameters always represent a struct (fields and values), I was attempting to use a struct to populate both the fields and values rather than complete each manually. Fields is fairly simple with reflection, however the values are of multiple types with the AddRow function defined as:
AddRow func(values ...driver.Value) *Rows
Is there a way to loop over struct fields and provide typed values to achieve something like?...
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())
This can be done with the reflect
package which allows you to loop over a struct's fields and then construct a slice of driver.Value
s. You would then pass the resulting slice to AddRow
with the trailing ...
to "unpack" the contents.
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...)
Note that in this case the conversion driver.Value(fv.Interface())
works because driver.Value
is an empty interface and so is the type returned by fv.Interface()
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.