I want to create structs = each type of command.
Commands have common part of xml - CommandResult. I created interface Command. I need to SomeCommand implements Command and can to be parsed as xml, also IsError must be realized in CommandResult, other functions must be realized by SomeCommand.
Code:
type Command interface {
IsError() bool
Request(buf *bufio.Writer, params interface{}) error
...
}
// Result of request
type CommandResult struct {
Code int `xml:"code,attr" json:"code"`
Message string `xml:"msg" json:"msg"`
}
// this Command's func is realized by CommandResult
func (self CommandResult) IsError() bool {
return true
}
// some command
type SomeCommand struct {
CommandResult // CommandResult `xml:"response>result" json:"result"`
}
// this Command's func is realized by SomeCommand
func (self SomeCommand) Request(buf *bufio.Writer, params interface{}) error {
return nil
}
// other Command's functions are realized by CommandResult too
XML:
<epp>
<response>
<result code="1000">
<msg>Command completed successfully</msg>
</result>
<trID>
<svTRID>asd</svTRID>
</trID>
</response>
</epp>
Expected result:
a := SomeCommand
xml.NewDecoder(reader).Decode(&a)
// a.CommandResult.Code = 1000
// a.CommandResult.Message = 'Command completed successfully'
// a implements Command
I think paths in embedded structure should be absolute as all "parent's" structures are part of the "child". So your
type CommandResult struct {
Code int `xml:"code,attr" json:"code"`
Message string `xml:"msg" json:"msg"`
}
Should be more like
type CommandResult struct {
Code int `xml:"response>result>code,attr" json:"code"`
Message string `xml:"response>result>msg" json:"msg"`
}
BUT! There we are facing Go's limitation.
You can't use attr
with chaining. There is issue on Github but looks like it is not in priority list. So if I right understand shortest version of your CommandResult
declaration would be:
type CommandResult struct {
Result struct {
Code int `xml:"code,attr" json:"code"`
Message string `xml:"msg" json:"msg"`
} `xml:"response>result" json:"response"`
}
Not a real problem but in case if you will decide to convert Command
back to XML would be nice to declare its XMLName
. Something like
type CommandResult struct {
XMLName xml.Name `xml:"epp"`
Result struct {
Code int `xml:"code,attr" json:"code"`
Message string `xml:"msg" json:"msg"`
} `xml:"response>result" json:"response"`
}
Because without it XML encoder will produce something like <SomeCommand><response>...</response></SomeCommand>
Update with full example
package main
import (
"bufio"
"encoding/xml"
"log"
)
type Command interface {
IsError() bool
Request(buf *bufio.Writer, params interface{}) error
}
// Result of request
type CommandResult struct {
XMLName xml.Name `xml:"epp"`
Result struct {
Code int `xml:"code,attr" json:"code"`
Message string `xml:"msg" json:"msg"`
} `xml:"response>result" json:"response"`
}
// this Command's func is realized by CommandResult
func (self CommandResult) IsError() bool {
return true
}
// some command
type SomeCommand struct {
CommandResult
}
// this Command's func is realized by SomeCommand
func (self SomeCommand) Request(buf *bufio.Writer, params interface{}) error {
return nil
}
type AnotherCommand struct {
CommandResult
}
func (self AnotherCommand) Request(buf *bufio.Writer, params interface{}) error {
return nil
}
func main() {
var c Command
c = SomeCommand{}
log.Println(c.IsError())
c = AnotherCommand{}
log.Println(c.IsError())
}