-
-
Notifications
You must be signed in to change notification settings - Fork 465
Description
First of all, thanks for you amazing library!
I'm facing some error when I'm using some dynamic unmarshalling of protobuf messages in the program context, the unmarshalled types are interface{} | *interface{} | *<STRUCT CONCRETE TYPE>.
When I'm trying to access a field of the struct, I'm getting the error: cannot fetch Value from *interface{}.
Here is a concrete example where I'm reproducing the error:
func TestExpr_fetch_from_interface(t *testing.T) {
type FooBar struct {
Value string
}
foobar := &FooBar{"waldo"}
var foobarAny any = foobar
var foobarPtrAny any = &foobarAny
res, err := expr.Eval("foo.Value", map[string]any{
"foo": foobarPtrAny,
})
assert.NoError(t, err)
assert.Equal(t, "waldo", res)
}And the error is:
=== RUN TestExpr_fetch_from_interface
expr_test.go:1218:
Error Trace: /opt/dev/go/expr/expr_test.go:1218
Error: Received unexpected error:
cannot fetch Value from *interface {} (1:5)
| foo.Value
| ....^
Test: TestExpr_fetch_from_interface
expr_test.go:1219:
Error Trace: /opt/dev/go/expr/expr_test.go:1219
Error: Not equal:
expected: string("waldo")
actual : <nil>(<nil>)
Test: TestExpr_fetch_from_interface
--- FAIL: TestExpr_fetch_from_interface (0.00s)
This was working fine with v1.12.5 but this not working anymore with v1.15.3.
The error is triggered in the Fetch method, here: https://github.com/antonmedv/expr/blob/5916dc2b68d01606f6c23e1b54da5ee3cd3dc79a/vm/runtime/runtime.go#L76
I'm wondering a simple fix could be to use a deref function like that:
func deref(kind reflect.Kind, value reflect.Value) (reflect.Kind, reflect.Value) {
for kind == reflect.Ptr || kind == reflect.Interface {
value = value.Elem()
kind = value.Kind()
}
return kind, value
}And use it instead of the if block here: https://github.com/antonmedv/expr/blob/5916dc2b68d01606f6c23e1b54da5ee3cd3dc79a/vm/runtime/runtime.go#L28-L34
Thanks for your help.
Happy to submit a PR with the fix if the deref solution is a valid option, or to implement any other idea for the fix.