fix: handling values in map of interfaces

This commit is contained in:
Marc Vertes
2020-04-22 10:34:05 +02:00
committed by GitHub
parent 3ed4ec3f6f
commit 7b2d91bcb5
5 changed files with 76 additions and 10 deletions

18
_test/map24.go Normal file
View File

@@ -0,0 +1,18 @@
package main
import (
"encoding/json"
"fmt"
)
func main() {
jb := []byte(`{"property": "test"}`)
params := map[string]interface{}{"foo": 1}
if err := json.Unmarshal(jb, &params); err != nil {
panic("marshal failed.")
}
fmt.Println(params["foo"], params["property"])
}
// Output:
// 1 test

26
_test/map25.go Normal file
View File

@@ -0,0 +1,26 @@
package main
import (
"encoding/json"
"strconv"
)
func main() {
jb := []byte(`{"num": "2"}`)
params := map[string]interface{}{"foo": "1"}
if err := json.Unmarshal(jb, &params); err != nil {
panic(err)
}
sum := 0
for _, v := range params {
i, err := strconv.Atoi(v.(string))
if err != nil {
panic(err)
}
sum += i
}
println(sum)
}
// Output:
// 3

View File

@@ -659,7 +659,7 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
wireChild(n)
t := n.child[0].typ
switch t.cat {
case ptrT:
case aliasT, ptrT:
n.typ = t.val
if t.val.cat == valueT {
n.typ = &itype{cat: valueT, rtype: t.val.rtype.Elem()}

View File

@@ -1032,6 +1032,9 @@ func getIndexArray(n *node) {
}
}
// valueInterfaceType is the reflection type of valueInterface
var valueInterfaceType = reflect.TypeOf((*valueInterface)(nil)).Elem()
// getIndexMap retrieves map value from index
func getIndexMap(n *node) {
dest := genValue(n)
@@ -1057,7 +1060,11 @@ func getIndexMap(n *node) {
z = reflect.New(n.child[0].typ.val.frameType()).Elem()
n.exec = func(f *frame) bltn {
if v := value0(f).MapIndex(mi); v.IsValid() {
dest(f).Set(v.Elem())
if e := v.Elem(); e.Type().AssignableTo(valueInterfaceType) {
dest(f).Set(e)
} else {
dest(f).Set(reflect.ValueOf(valueInterface{n, e}))
}
} else {
dest(f).Set(z)
}
@@ -1091,7 +1098,11 @@ func getIndexMap(n *node) {
z = reflect.New(n.child[0].typ.val.frameType()).Elem()
n.exec = func(f *frame) bltn {
if v := value0(f).MapIndex(value1(f)); v.IsValid() {
dest(f).Set(v.Elem())
if e := v.Elem(); e.Type().AssignableTo(valueInterfaceType) {
dest(f).Set(e)
} else {
dest(f).Set(reflect.ValueOf(valueInterface{n, e}))
}
} else {
dest(f).Set(z)
}
@@ -1137,7 +1148,11 @@ func getIndexMap2(n *node) {
n.exec = func(f *frame) bltn {
v := value0(f).MapIndex(mi)
if v.IsValid() {
dest(f).Set(v.Elem())
if e := v.Elem(); e.Type().AssignableTo(valueInterfaceType) {
dest(f).Set(e)
} else {
dest(f).Set(reflect.ValueOf(valueInterface{n, e}))
}
}
if doStatus {
value2(f).SetBool(v.IsValid())
@@ -1169,7 +1184,11 @@ func getIndexMap2(n *node) {
n.exec = func(f *frame) bltn {
v := value0(f).MapIndex(value1(f))
if v.IsValid() {
dest(f).Set(v.Elem())
if e := v.Elem(); e.Type().AssignableTo(valueInterfaceType) {
dest(f).Set(e)
} else {
dest(f).Set(reflect.ValueOf(valueInterface{n, e}))
}
}
if doStatus {
value2(f).SetBool(v.IsValid())
@@ -1900,7 +1919,11 @@ func rangeMap(n *node) {
return fnext
}
f.data[index0].Set(iter.Key())
f.data[index1].Set(iter.Value().Elem())
if e := iter.Value().Elem(); e.Type().AssignableTo(valueInterfaceType) {
f.data[index1].Set(e)
} else {
f.data[index1].Set(reflect.ValueOf(valueInterface{n, e}))
}
return tnext
}
} else {

View File

@@ -79,7 +79,7 @@ func genValue(n *node) func(*frame) reflect.Value {
case basicLit:
v := n.rval
if !v.IsValid() {
v = reflect.New(reflect.TypeOf((*interface{})(nil)).Elem()).Elem()
v = reflect.New(interf).Elem()
}
return func(f *frame) reflect.Value { return v }
case funcDecl:
@@ -149,10 +149,9 @@ func genValueRangeArray(n *node) func(*frame) reflect.Value {
func genValueInterfacePtr(n *node) func(*frame) reflect.Value {
value := genValue(n)
it := reflect.TypeOf((*interface{})(nil)).Elem()
return func(f *frame) reflect.Value {
v := reflect.New(it).Elem()
v := reflect.New(interf).Elem()
v.Set(value(f))
return v.Addr()
}
@@ -179,7 +178,7 @@ func genValueInterface(n *node) func(*frame) reflect.Value {
func zeroInterfaceValue() reflect.Value {
n := &node{kind: basicLit, typ: &itype{cat: nilT, untyped: true}}
v := reflect.New(reflect.TypeOf((*interface{})(nil)).Elem()).Elem()
v := reflect.New(interf).Elem()
return reflect.ValueOf(valueInterface{n, v})
}