How to compare data using Reflection between struct and map[string]interface{} in Golang - go

I am trying to compare these two interfaces together as a function. It is working as far as I am concerned. I am sending a struct in A interface{} and map[string]interface{} in B, having the same values but when being compared with reflect they are not resulting to be the same. I would like to be able to convert the map[string]interface{} into a struct interface inside this function so that my tests can get shorter. I have tried using https://github.com/mitchellh/copystructure, but does not work inside this function.(from outside it works though:
var m map[string]interface{}
var something StructType
err := mapstructure.Decode(m, &something)
if err....
and then i send the something in the B interface)
below is the function to compare the interfaces. You can copy and paste and see how it works for yourself
package main
import (
"log"
"reflect"
)
type Something struct {
Name string
Age int
Male bool
Cars []string
}
func main() {
var s Something
s.Name = "joe"
s.Male = true
s.Age = 20
s.Cars = []string{"Fordd", "Chevy", "Mazda"}
m := make(map[string]interface{})
m["Name"] = "joe"
m["Male"] = true
m["Age"] = 20
m["Cars"] = []string{"Fordd", "Chevy", "Mazda"}
//with map[string]interface{} although the same values it does not work
log.Println("Are these the same: ", CompareData(s, m))
//with struct of same type it works
var s2 Something
s2.Name = "joe"
s2.Male = true
s2.Age = 20
s2.Cars = []string{"Fordd", "Chevy", "Mazda"}
log.Println("Are these the same: ", CompareData(s, s2))
}
func CompareData(A interface{}, B interface{}) bool {
a := reflect.ValueOf(A)
b := reflect.ValueOf(B)
akind := a.Kind().String()
bkind := a.Kind().String()
if akind == "slice" && bkind == "slice" {
for i := 0; i < a.Len(); i++ {
// log.Println("they are sliced")
CompareData(a.Index(i).Interface(), b.Index(i).Interface())
// log.Println("\n", a.Index(i).Interface(), "\n", b.Index(i).Interface())
}
// t.Fatal("this is a slice you need to iterate over the values")
} else {
// log.Println("\n\n", A, "\n", B)
if !reflect.DeepEqual(a.Interface(), b.Interface()) {
log.Println("These should be equal\nSuccessData:\t", a.Interface(), "\nData:\t\t", b.Interface())
return false
}
// log.Println("\nA:\t", A, "\nB:\t", B)
}
return true
}

Related

Go: A function that would consume maps with different types of values

In my code, I need a function that would return an ordered slice of keys from a map.
m1 := make(map[string]string)
m2 := make(map[string]int)
And now I need to call a function passing both types of maps:
keys1 := sortedKeys(m1)
keys2 := sortedKeys(m1)
Problem: I have to write two functions because the function should consume maps of two different types. At the same time, the body of the function will be the same in both cases.
Question: How can I use a single implementation for two maps? Or is there any other way of solving the problem in an elegant way?
My first idea was to use map[string]interface{} as an argument type, but you can't assign neither map[string]string, nor map[string]int to it.
My code:
func sortedKeys(m map[string]string) []string {
var keys []string
for key := range m {
keys = append(keys, key)
}
sort.Strings(keys)
return keys
}
I would have to repeat the same code but for map[string]int.
You can use interface{} and use reflection for achieving this.
You can write two functions for the same but it is just not scalable, say, you are supporting string and int now but you wish to support int64, float64, bool or struct in the future. Having a common function using map[string]interface{} and using reflection is the way to go.
Suggested Code :
package main
import (
"fmt"
"reflect"
)
func main() {
m1 := make(map[string]string)
m2 := make(map[string]int)
m1["a"] = "b"
m1["b"] = "c"
m2["a"] = 1
m2["b"] = 2
fmt.Println(sortedKeys(m1))
fmt.Println(sortedKeys(m2))
}
// Returns slice of values in the type which is sent to it
func sortedKeys(m interface{}) interface{} {
if m == nil {
return nil
}
if reflect.TypeOf(m).Kind() != reflect.Map {
return nil
}
mapIter := reflect.ValueOf(m).MapRange()
mapVal := reflect.ValueOf(m).Interface()
typ := reflect.TypeOf(mapVal).Elem()
outputSlice := reflect.MakeSlice(reflect.SliceOf(typ), 0, 0)
for mapIter.Next() {
outputSlice = reflect.Append(outputSlice, mapIter.Value())
}
return outputSlice.Interface()
}
Output :
[b c]
[1 2]
https://play.golang.org/p/2fkpydH9idG

Comparing superset object in golang

I want to compare two objects
expected:= `"{\"method\":\"GET\",\"body\":{},\"uploadCount\":0}"`
result := `"{\"name\":\"xyz\",\"method\":\"GET\",\"body\":{},\"uploadCount\":0}"`
Now as we can see result is super-set of expected but when I use reflect.deepequal, it says false because it exactly compare two objects. I want to compare if result is superset of expected or not.
func main(){
result := "{\"name\":\"xyz\",\"method\":\"GET\",\"body\":{},\"uploadCount\":0}"
expected := "{\"method\":\"GET\",\"body\":{},\"uploadCount\":0}"
var _result interface{}
var _expected interface{}
json.Unmarshal([]byte(result),&_result)
json.Unmarshal([]byte(expected),&_expected)
reflect.deepequal(_result,_expected)
}
Without any refinements you could do something like
func main() {
result := "{\"name\":\"xyz\",\"method\":\"GET\",\"body\":{},\"uploadCount\":0}"
expected := "{\"method\":\"GET\",\"body\":{},\"uploadCount\":0}"
var _result map[string]interface{}
var _expected map[string]interface{}
json.Unmarshal([]byte(result), &_result)
json.Unmarshal([]byte(expected), &_expected)
isSuperset := true
for k, v := range _expected {
if !reflect.DeepEqual(v, _result[k]) {
isSuperset = false
break
}
}
fmt.Println(isSuperset)
}

Struct containing embedded slice of struct

I have this code
package main
import (
"fmt"
)
type foo struct {
a int
b bool
}
type foos []foo
type bar struct {
foos
}
func newBar() *bar {
b := &bar{
foos: make([]foo, 3, 3),
}
for _, foo := range b.foos {
// didn't set b to true
foo.b = true
}
return b
}
func main() {
b := newBar()
fmt.Println(b)
// set b to true
b.foos[0].b = true
fmt.Println(b)
}
The Go Playground
As you can see I want to initialize bar using constructor newBar() but I want the embed type foo.b is initialize with non zero value so I initialize with for range statement but it didn't work as intended, the foo.b is still false, all of them. As comparison in the main function using this code b.foos[0].b = true it work. So whats wrong with my code?
Omg, I just realized this after posting this question, it's because variable slot is local to for loop. So the solution is:
for i, _ := range b.foos {
// now b is set to true
b.foos[i].b = true
}

How to access unexported struct fields

Is there a way to use reflect to access unexported fields in Go 1.8?
This no longer seems to work: https://stackoverflow.com/a/17982725/555493
Note that reflect.DeepEqual works just fine (that is, it can access unexported fields) but I can't make heads or tails of that function. Here's a go playarea that shows it in action: https://play.golang.org/p/vyEvay6eVG. The src code is below
import (
"fmt"
"reflect"
)
type Foo struct {
private string
}
func main() {
x := Foo{"hello"}
y := Foo{"goodbye"}
z := Foo{"hello"}
fmt.Println(reflect.DeepEqual(x,y)) //false
fmt.Println(reflect.DeepEqual(x,z)) //true
}
If the struct is addressable, you can use unsafe.Pointer to access the field (read or write) it, like this:
rs := reflect.ValueOf(&MyStruct).Elem()
rf := rs.Field(n)
// rf can't be read or set.
rf = reflect.NewAt(rf.Type(), unsafe.Pointer(rf.UnsafeAddr())).Elem()
// Now rf can be read and set.
See full example on the playground.
This use of unsafe.Pointer is valid according to the documentation and running go vet returns no errors.
If the struct is not addressable this trick won't work, but you can create an addressable copy like this:
rs = reflect.ValueOf(MyStruct)
rs2 := reflect.New(rs.Type()).Elem()
rs2.Set(rs)
rf = rs2.Field(0)
rf = reflect.NewAt(rf.Type(), unsafe.Pointer(rf.UnsafeAddr())).Elem()
// Now rf can be read. Setting will succeed but only affects the temporary copy.
See full example on the playground.
Based on cpcallen's work:
import (
"reflect"
"unsafe"
)
func GetUnexportedField(field reflect.Value) interface{} {
return reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())).Elem().Interface()
}
func SetUnexportedField(field reflect.Value, value interface{}) {
reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())).
Elem().
Set(reflect.ValueOf(value))
}
reflect.NewAt might be confusing to read at first. It returns a reflect.Value representing a pointer to a value of the specified field.Type(), using unsafe.Pointer(field.UnsafeAddr()) as that pointer. In this context reflect.NewAt is different than reflect.New, which would return a pointer to a freshly initialized value.
Example:
type Foo struct {
unexportedField string
}
GetUnexportedField(reflect.ValueOf(&Foo{}).Elem().FieldByName("unexportedField"))
https://play.golang.org/p/IgjlQPYdKFR
reflect.DeepEqual() can do it because it has access to unexported features of the reflect package, in this case namely for the valueInterface() function, which takes a safe argument, which denies access to unexported field values via the Value.Interface() method if safe=true. reflect.DeepEqual() will (might) call that passing safe=false.
You can still do it, but you cannot use Value.Interface() for unexported fields. Instead you have to use type-specific methods, such as Value.String() for string, Value.Float() for floats, Value.Int() for ints etc. These will return you a copy of the value (which is enough to inspect it), but will not allow you to modify the field's value (which might be "partly" possible if Value.Interface() would work and the field type would be a pointer type).
If a field happens to be an interface type, you may use Value.Elem() to get to the value contained / wrapped by the interface value.
To demonstrate:
type Foo struct {
s string
i int
j interface{}
}
func main() {
x := Foo{"hello", 2, 3.0}
v := reflect.ValueOf(x)
s := v.FieldByName("s")
fmt.Printf("%T %v\n", s.String(), s.String())
i := v.FieldByName("i")
fmt.Printf("%T %v\n", i.Int(), i.Int())
j := v.FieldByName("j").Elem()
fmt.Printf("%T %v\n", j.Float(), j.Float())
}
Output (try it on the Go Playground):
string hello
int64 2
float64 3
package main
import (
"fmt"
"reflect"
"strings"
"unsafe"
)
type Person1 struct {
W3ID string
Name string
}
type Address1 struct {
city string
country string
}
type User1 struct {
name string
age int
address Address1
manager Person1
developer Person1
tech Person1
}
func showDetails(load, email interface{}) {
if reflect.ValueOf(load).Kind() == reflect.Struct {
typ := reflect.TypeOf(load)
value := reflect.ValueOf(load)
//#1 For struct, not addressable create a copy With Element.
value2 := reflect.New(value.Type()).Elem()
//#2 Value2 is addressable and can be set
value2.Set(value)
for i := 0; i < typ.NumField(); i++ {
if value.Field(i).Kind() == reflect.Struct {
rf := value2.Field(i)
/* #nosec G103 */
rf = reflect.NewAt(rf.Type(), unsafe.Pointer(rf.UnsafeAddr())).Elem()
irf := rf.Interface()
typrf := reflect.TypeOf(irf)
nameP := typrf.String()
if strings.Contains(nameP, "Person") {
//fmt.Println(nameP, "FOUND !!!!!!! ")
for j := 0; j < typrf.NumField(); j++ {
re := rf.Field(j)
nameW := typrf.Field(j).Name
if strings.Contains(nameW, "W3ID") {
valueW := re.Interface()
fetchEmail := valueW.(string)
if fetchEmail == email {
fmt.Println(fetchEmail, " MATCH!!!!")
}
}
}
}
showDetails(irf, email)
} else {
// fmt.Printf("%d.Type:%T || Value:%#v\n",
// (i + 1), value.Field(i), value.Field(i))
}
}
}
}
func main() {
iD := "tsumi#in.org.com"
load := User1{
name: "John Doe",
age: 34,
address: Address1{
city: "New York",
country: "USA",
},
manager: Person1{
W3ID: "jBult#in.org.com",
Name: "Bualt",
},
developer: Person1{
W3ID: "tsumi#in.org.com",
Name: "Sumi",
},
tech: Person1{
W3ID: "lPaul#in.org.com",
Name: "Paul",
},
}
showDetails(load, iD)
}

Iterate through struct in golang without reflect

I have a struct like this
import (
"fmt"
)
type Node struct {
m []string
o []string
}
func main() {
var mm = []string{"abc", "def"}
var oo = []string{"111", "222"}
var v = Node{m: mm, o: oo}
for _, d := range []interface{}{v.m, v.o} {
fmt.Println(d)
}
}
The output I get is,
[abc def]
[111 222]
My desired output is,
abc,111
def,222
I don't want to use reflect package because, I want to use native go built-ins as much as possible. If it becomes too burdensome I will fall back on reflect package.
Edit: I just realized my output doesn't match yours, do you want the letters paired with the numbers? If so then you'll need to re-work what you have.
You can use strings.Join and a type switch statement to accomplish this:
https://play.golang.org/p/ygtdxv02uK
package main
import (
"fmt"
"strings"
)
type Node struct {
m []string
o []string
p []int
}
func main() {
var mm = []string{"abc", "def"}
var oo = []string{"111", "222"}
var pp = []int{1, 2, 3}
var v = Node{m: mm, o: oo, p: pp}
for _, d := range []interface{}{v.m, v.o, v.p} {
switch d.(type) {
case []string:
fmt.Println(strings.Join(d.([]string), ","))
default:
fmt.Println(d)
}
}
}
The output is:
abc,def
111,222
[1 2 3]
Is there a reason you don't want to use the reflect package? like Iterate through a struct in Go and Iterate Over String Fields in Struct ?
From the former question, it seems like, yeah you can iterate without reflect by iterating through an interface of the fields, https://play.golang.org/p/bPWUII_D7q
package main
import (
"fmt"
)
type Foo struct {
num int
str string
}
func main() {
foo := &Foo{42, "Hello"} // struct with fields of many types...
for _, data := range []interface{}{foo.num, foo.str} {
fmt.Println(data)
}
}
Here is what I did,
package main
import (
"fmt"
)
type Node struct {
m []string
o []string
}
func main() {
var mm = []string{"abc", "def"}
var oo = []string{"111", "222"}
var v = Node{m: mm, o: oo}
for i := range v.m {
fmt.Println(v.m[i],v.o[i])
}
}
This gives me my desired output. Just one thing is I have to write v.m so I suppose I should still use reflect package.

Resources