I’m working on a project where I have two structs and I'd like to be able to perform the same logic on them without writing two different object methods, but I'm unsure how to enforce fields for an interface. For example, imagine I have the following two structs, with many differing fields but one that they share:
type Item1 struct {
itemField string
...some other fields
}
type Item2 struct {
itemField string
...some other fields that differ from those of Item1
}
And where these items have several differing functions, but one that they share:
func (Item1) ItemLogic() {
--some logic--
}
func (Item2) ItemLogic() {
--some different logic--
}
I want to group together a function that will do some upfront checks on these items before handling the item logic, but I don't want to have to write two separate functions to do so. I can write an interface so that I can pass both Item1 and Item2 in like so:
type IItem interface {
ItemLogic()
}
but I can't enforce that the fields that get passed in as part of the function have a a field itemField
, so that I could write a function like this:
func MainFunction(item IItem) {
if item.ItemField == "..." {
....
}
item.ItemLogic()
}
The problem here is I could theoretically pass in an item that has an ItemLogic
function but that lacks an ItemField
field, resulting in a nil pointer. Is there some way I'm unaware of to enforce that field? Or, is there some better design I'm missing? I imagine I could make use of the reflect package in Go to check if the passed in object has the field, but it feels messy (I'd rather just not allow someone to pass a bad object in). Is there a better way?
CodePudding user response:
You cannot do field-level operations on interfaces, because interfaces are by definition just method sets. You can, however, use an interface for getting the ItemField
:
type WithItemField interface {
GetItemField() string
}
And implement a GetItemField
method for types that have it.
Then you can check if an object has itemField:
func MainFunction(item IItem) {
if withItemField, ok:=item.(WithItemField); ok {
itemField:=withItemField.GetItemField()
// validate
}
item.ItemLogic()
}