Go: Enforce fields of object passed into function?

huangapple go评论83阅读模式
英文:

Go: Enforce fields of object passed into function?

问题

我正在进行一个项目,其中我有两个结构体,并且我希望能够对它们执行相同的逻辑,而不需要编写两个不同的对象方法,但我不确定如何强制执行接口的字段。例如,假设我有以下两个结构体,它们有许多不同的字段,但有一个共享的字段:

type Item1 struct {
	itemField            string
	...一些其他字段
}

type Item2 struct {
	itemField            string
    ...一些与Item1不同的其他字段
}

这些项有几个不同的函数,但有一个共享的函数:

func (Item1) ItemLogic() {
	--一些逻辑--
}

func (Item2) ItemLogic() {
	--一些不同的逻辑--
}

我想将一个函数分组起来,在处理项逻辑之前对这些项进行一些前期检查,但我不想编写两个单独的函数来实现。我可以编写一个接口,以便可以像这样传递Item1和Item2:

type IItem interface {
	ItemLogic()
}

但是,我无法强制要求作为函数一部分传递的字段具有一个名为itemField的字段,这样我就可以编写这样一个函数:

func MainFunction(item IItem) {
    if item.ItemField == "..." {
          ....
    }

    item.ItemLogic()
}

问题在于,理论上我可以传递一个具有ItemLogic函数但缺少ItemField字段的项,导致空指针。我是否有一些未知的方法来强制执行该字段?或者,是否有一些更好的设计我没有考虑到?我想我可以利用Go中的反射包来检查传入的对象是否具有该字段,但这样做感觉很混乱(我宁愿不允许某人传递一个错误的对象)。有更好的方法吗?

英文:

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?

答案1

得分: 1

你不能在接口上进行字段级操作,因为接口本质上只是方法集合。但是,你可以使用接口来获取ItemField

type WithItemField interface {
  GetItemField() string
}

并为具有该方法的类型实现一个GetItemField方法。

然后,你可以检查一个对象是否具有itemField

func MainFunction(item IItem) {
    if withItemField, ok := item.(WithItemField); ok {
        itemField := withItemField.GetItemField()
        // 验证
    }

    item.ItemLogic()
}
英文:

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()
}

huangapple
  • 本文由 发表于 2022年9月24日 01:15:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/73831025.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定