I am trying to implement a struct that will pass one of several structs to a function that will convert the data to XML. A simple working example of passing a string to xml.Unmarshal() works as expected:
As DataStruct is an empty nterface i guess you have to cast to a specifi type. For example
data := x.DataStruct.(XmlData)
to be able to parse the xml string…
t := reflect.TypeOf(x.DataStruct)
switch t.Kind() {
case reflect.Struct:
fmt.Printf("%v\n", t)
data := x.DataStruct.(XmlData)
xml.Unmarshal([]byte(rawXml),&data)
fmt.Printf("The value of data is: %v\n",data)
out, _ := xml.Marshal(data)
fmt.Printf("The value of out is: %s\n",string(out))
}
Unfortunately I will be needing to handle literally dozens of structs so that approach would be impractical. Anything that would involve a type switch would become unmanageable.
I gave up…Everything I tried (and I’m sure I missed something) to get the xml.Unmarshal() to work correctly with an interface{} failed. And I couldn’t figure out an easy way to get the struct. So, at least for now, I’m using a type switch and instantiating the struct directly without reflect.
As I mentioned before, while that works, in my actual application I won’t know the data type coming in, and I will be using potentially dozens of types. So if I end up having to do a type switch anyway, I might as well not bother with defining the DataStruct as an interface.
I can’t really help with determining which struct to use because you pretty much have to do some kind of switch statement. Perhaps, you could add a required field such as tag which includes the xml’s type but you’d need a dummy struct to load that in. As for sending the struct to another function you’re going to want to create an interface that all the structs complete. Such as getName xml.Name and getValue []string that way the receiving function can always get the name, and loop through the values. I’m not sure what the ultimate goal is of what you’re trying to do but here is some code that may help spark something new. https://play.golang.org/p/pyrpm0RHSNb
EDIT: I came up with a better way than using a switch statement. You can use a map where the key is the tag field and the value is the struct that should be used to unmarshal. So something like map[string]XmlInterface. Doing it this way means you only need to do one check - an error check to see if the struct was found.
Actually, I realized that all the xml.Unmarshal() and xml.Marshal() end up doing is first converting the XML string into a struct and then converting the struct into a byte slice. So, technically, after removing the extra spaces between the tags (I format the XML string with newlines and tabs to make it easier to read) all I really needed to do was convert the string to a byte slice and voila…So I’m no longer using xml.(Unm/M)arshal.