Last active
October 30, 2020 19:46
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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