type BizError struct {
Code string
Mesg string
}
type ApiReply struct {
Err BizError
}
type GetDataReply struct {
Data interface{}
ApiReply
}
with the above definition, I want to do the following:
func Func1(data interface{}) {
switch data.(type) {
case ApiReply:
data.(ApiReply).Err.Code = "0"
}
}
The key problem is that in Func1, the type-switch does not know any new types that embeds ApiReply, it is a "generic" handler. While the data
passed to it is actually ApiReply's "child class". Apparently, in Go, you cannot assert a GetDataReply type to an ApiReply.
How can I handle this case so that in Func1 I do not need to have all possible structs that may embed ApiReply explicitly declared?
You're trying to implement an inheritance style system in go. Struct embedding is not inheritance and should not be thought of or treated as such. This is an anti-pattern in go and generally does not work as you would desire or expect.
Instead, the more idiomatic approach to this would be to define an interface (or a couple interfaces) and have your response types implement the necessary methods to conform.
type ApiReply interface {
Status() (string, string)
Body() (io.Reader, error)
}
type BizError struct {
Code string
Mesg string
}
func (b BizError) Status() (string, string) {
return b.Code, b.Mesg
}
func (b BizError) Body() (io.Reader, error) {
return nil, errors.New("BizError never contains a body")
}
You would then implement ApiReply
on your other response type structs. I'm of course guessing at what you actually need here but hopefully this gets the point across.
And if you find you must, you can now do a type switch against the ApiReply
instance you receive and special case any underlying types if absolutely necessary.