Skip to content

Instantly share code, notes, and snippets.

@brunolkatz
Last active October 30, 2020 19:46
Show Gist options
  • Save brunolkatz/d7d10667fc8f04fb671bbe768945ad01 to your computer and use it in GitHub Desktop.
Save brunolkatz/d7d10667fc8f04fb671bbe768945ad01 to your computer and use it in GitHub Desktop.
Scan a map[string]interface{} and fill without passing the ptr in function parameter using reflect.Indirect function.
package main
import (
"errors"
"fmt"
"reflect"
)
func main() {
columns := []string{"FirstName", "LastName", "teste"} // Determine the columns names
//values := make([]interface{}, len(columns))
rows := [][]interface{}{}
string_names := [][]string{{"first", "second"}, {"first2", "second2"}} // Fill columns
for _, row := range string_names {
c := []interface{}{}
for _, r := range row {
c = append(c, r)
}
rows = append(rows, c)
}
nonUsers := &[]map[string]interface{}{}
err := Scan(nonUsers, columns, rows)
if err != nil {
panic(err)
}
fmt.Println(nonUsers)
return
}
func Scan(dest interface{}, columns []string, rows interface{}) error {
switch dest := dest.(type) {
case map[string]interface{}, *map[string]interface{}:
mapValue, ok := dest.(map[string]interface{})
if !ok {
if v, ok := dest.(*map[string]interface{}); ok {
mapValue = *v
}
}
if r, ok := rows.([]interface{}); ok {
values := GetValues(columns, r)
scanIntoMap(mapValue, values, columns)
}else{
if r, ok := rows.([][]interface{}); ok {
values := r
if len(values) == 0 {
return nil
}
scanIntoMap(mapValue, values[0], columns)
}else{
if c, ok := rows.([]interface{}); ok {
scanIntoMap(mapValue, c, columns)
}else{
return errors.New("invalid type assertion")
}
}
}
case *[]map[string]interface{}:
if r, ok := rows.([][]interface{}); ok {
for _, r := range r {
mapValue := map[string]interface{}{}
scanIntoMap(mapValue, r, columns)
*dest = append(*dest, mapValue)
}
}else{
mapValue := map[string]interface{}{}
if r, ok := rows.([]interface{}); ok {
values := GetValues(columns, r)
scanIntoMap(mapValue, values, columns)
}else{
values := r
scanIntoMap(mapValue, values, columns)
}
*dest = append(*dest, mapValue)
}
}
return nil
}
func scanIntoMap(mapValue map[string]interface{}, values []interface{}, columns []string) {
for idx, column := range columns {
if idx > (len(values)-1) {
values = append(values, nil)
}
if reflectValue := reflect.Indirect(reflect.Indirect(reflect.ValueOf(values[idx]))); reflectValue.IsValid() {
mapValue[column] = reflectValue.Interface()
} else {
mapValue[column] = nil
}
}
}
func GetValues (columns []string, row []interface{}) []interface{}{
values := make([]interface{}, len(columns))
for idx := range columns {
if idx > (len(row) - 1) {
values[idx] = nil
} else {
values[idx] = row[idx]
}
}
return values
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment