I am trying to dynamically design a protocol test.
The function which I need to use is go-ethereum's Decode
: https://github.com/ethereum/go-ethereum/blob/master/p2p/message.go#L54
Then some of my code uses it:
msg <- receive() //sends me a message of type p2p.Msg
var message MyTargetType
msg.Decode(&message) // this works correctly and this is apparently the correct way to use the function, with a pointer to the variable
anotherMessage := output.Msg // this is an interface{}, see below
msg.Decode(&anotherMessage) // this fails
I don't understand why the Decode
method handles the two differently. A little test program:
package main
import (
"fmt"
"reflect"
)
type mystruct struct {
hello string
}
func main() {
var first mystruct
second := mystruct{}
fmt.Println(reflect.TypeOf(first))
fmt.Println(reflect.TypeOf(second))
}
This prints the types to be the same:
main.mystruct
main.mystruct
But somehow, Decode
above, which uses reflection internally, handles them differently.
What's my problem? For my protocol test, I want to define the type of the output to be expected:
type Output struct {
Msg interface{}
}
Since the messages can be of very different type, I thought the only way is to use interface{}
. Therefore:
output := Output{
Msg: MyTargetType{}.
}
//
anotherOutput := Output{
Msg: AnotherType{}.
}
// and so on
so that I then later can check that the output received is the one expected. But that Decode
method is driving me crazy.
I have tried several things with reflection, e.g.
var decodedMsg = reflect.TypeOf(output.Msg)
msg.Decode(&decodedMsg)
or even
var decodedMsg = reflect.New(reflect.TypeOf(output.Msg)).Elem().Interface()
fmt.Println(reflect.TypeOf(decodedMsg)) //this actually prints the correct type!!!
// But then Decode fails nonetheless with:
// interface given to Decode must be a pointer