Reputation: 1530
I'm looking to understand which is the most suitable approach to solve the following problem.
I have a struct that represents the data to be serialised as part of a JSON response. A property on this struct config
can be one of three possible structs, however, the only way I know to represent this is using the type interface{}
and have the caller type assert the property.
type Response struct {
Field1 string `json:"field1"`
Field2 int `json:"field2"`
Config interface{} `json:"config"`
}
type ConfigOne struct {
SomeField string
}
type ConfigTwo struct {
SomeField int
}
type ConfigThree struct {
SomeField bool
}
Then I can have New
style functions to create the right instance for me:
func NewConfigTwo() *Response {
return &Response{
Field1: "hello",
Field2: 1,
Config: ConfigTwo{
SomeField: 22,
},
}
}
Is there a better way to represent a field with a enum like type of structs? Or is this as good as I can make it?
I'd appreciate any clarity or suggestions on how best to achieve this.
Upvotes: 2
Views: 223
Reputation: 273366
Essentially, you're trying to implement an algebraic data type here. To expand on @mkopriva's comment, take a look at this post: Go and algebraic data types. Essentially you'll specify a non-empty interface such that all possible types implement a method and others don't satisfy the interface "by chance" (whereas every type implements interface{}
) and then use type switches.
Something like (untested):
type Response struct {
Field1 string `json:"field1"`
Field2 int `json:"field2"`
Config Configable `json:"config"`
}
type Configable interface {
isConfig()
}
type ConfigOne struct {
SomeField string
}
func (ConfigOne) isConfig() {}
// ... and so on for other Config* types
Upvotes: 2