合并两个函数,它们唯一的区别是参数类型。

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

Go - Merging 2 functions whose only difference is the arguments type

问题

我有这两个几乎完全相同的函数:

第一个

func mergeSlicesOfRequestObjects(aSliceDestination *[]RequestObject, aSliceSource []RequestObject) {
    for _, oSliceSourceItem := range aSliceSource {
        // 获取当前键
        iIndexSourceItemFound := -1
        for iIndexAttribute, oSliceDestinationItem := range *aSliceDestination {
            if oSliceSourceItem.Key == oSliceDestinationItem.Key {
                iIndexSourceItemFound = iIndexAttribute
                break
            }
        }

        // 更新属性
        if iIndexSourceItemFound == -1 {
            *aSliceDestination = append(*aSliceDestination, oSliceSourceItem)
        }
    }
}

第二个

func mergeSlicesOfResponseObjects(aSliceDestination *[]ResponseObject, aSliceSource []ResponseObject) {
    for _, oSliceSourceItem := range aSliceSource {
        // 获取当前键
        iIndexSourceItemFound := -1
        for iIndexAttribute, oSliceDestinationItem := range *aSliceDestination {
            if oSliceSourceItem.Key == oSliceDestinationItem.Key {
                iIndexSourceItemFound = iIndexAttribute
                break
            }
        }

        // 更新属性
        if iIndexSourceItemFound == -1 {
            *aSliceDestination = append(*aSliceDestination, oSliceSourceItem)
        }
    }
}

如你所见,这两个函数的唯一区别是参数的结构类型。

所以我的问题是:有没有办法将这两个函数合并成一个函数?

我尝试使用接口,但是我无法弄清楚...

提前感谢你的回答 合并两个函数,它们唯一的区别是参数类型。

祝好

编辑

我已经实现了这个答案,但是我遇到了错误。这是我做的:

type Request struct {
    Headers []RequestObject
}

type RequestObject struct {
    Key string
}

type Keyer interface {
    GetKey() string
}

func (oRequestObject RequestObject) GetKey() string {
    return oRequestObject.Key
}

func mergeKeyers(aDst *[]Keyer, aSrc []Keyer) {
    // 逻辑
}

func test() {
    // rDst 和 rSrc 是 Request 结构体
    mergeKeyers(&rDst.Headers, rSrc.Headers)
}

当执行 test() 时,我得到了以下错误:

cannot use &rDst.Headers (type *[]RequestObject) as type *[]Keyer in argument to mergeKeyers
cannot use rSrc.Headers (type []RequestObject) as type []Keyer in argument to mergeKeyers

有任何想法为什么会出现这个错误?

英文:

I have those 2 almost exact functions :

Number 1:

func mergeSlicesOfRequestObjects(aSliceDestination *[]RequestObject, aSliceSource []RequestObject) {
for _, oSliceSourceItem := range aSliceSource {
	// Get current key
	iIndexSourceItemFound := -1
	for iIndexAttribute, oSliceDestinationItem := range *aSliceDestination {
		if oSliceSourceItem.Key == oSliceDestinationItem.Key {
			iIndexSourceItemFound = iIndexAttribute
			break
		}
	}

	// Update attribute
	if iIndexSourceItemFound == -1 {
		*aSliceDestination = append(*aSliceDestination, oSliceSourceItem)
	}
}
}

Number 2:

func mergeSlicesOfResponseObjects(aSliceDestination *[]ResponseObject, aSliceSource []ResponseObject) {
for _, oSliceSourceItem := range aSliceSource {
	// Get current key
	iIndexSourceItemFound := -1
	for iIndexAttribute, oSliceDestinationItem := range *aSliceDestination {
		if oSliceSourceItem.Key == oSliceDestinationItem.Key {
			iIndexSourceItemFound = iIndexAttribute
			break
		}
	}

	// Update attribute
	if iIndexSourceItemFound == -1 {
		*aSliceDestination = append(*aSliceDestination, oSliceSourceItem)
	}
}
}

As you can see the only difference is the struct type of the arguments of the functions.

So here is my question : is there any way to merge those 2 functions into one ?

I've tried using interfaces but I can't figure it out...

Thanks for all the answer in advance 合并两个函数,它们唯一的区别是参数类型。

Cheers

EDIT

I've implemented thwd answer but I'm getting errors. Here's what I've done:

type Request struct {
    Headers         []RequestObject
}

type RequestObject {
    Key string
}

type Keyer interface {
    GetKey() string
}

func (oRequestObject RequestObject) GetKey() string {
    return oRequestObject.Key
}

func mergeKeyers(aDst *[]Keyer, aSrc []Keyer) {
    // Logic
}

func test() {
    // rDst and rSrc are Request struct
    mergeKeyers(&rDst.Headers, rSrc.Headers)
}

And I'm getting the following errors when executing test():

cannot use &rDst.Headers (type *[]RequestObject) as type *[]Keyer in argument to mergeKeyers
cannot use rSrc.Headers (type []RequestObject) as type []Keyer in argument to mergeKeyers

Any idea why ?

答案1

得分: 4

定义一个接口:

type Keyer interface {
    Key() int // 或者 Key 字段的任何类型
}

然后在两种类型上实现该接口:

func (r RequestObject) Key() int {
    return r.Key
}

func (r ResponseObject) Key() int {
    return r.Key
}

并且重写你的函数以接受这个接口(不使用匈牙利命名法和无尽的长变量名):

func mergeKeyers(dst *[]Keyer, src []Keyer) {
    for _, s := range src {
        f := -1
        for i, d := range *dst {
            if s.Key() == d.Key() {
                f = i
                break
            }
        }
        if f == -1 {
            *dst = append(*dst, s)
        }
    }
}

还要考虑 Dave C 的评论:

你使用了一个 O(n*m) 的算法,而你可以使用一个 O(n+m) 的算法。

我将把优化代码的工作留给你。


编辑以回答你的第二个问题:

类型 *[]RequestObject*[]Keyer 是不同的,不能互换。你需要做的是将你的 RequestObjects 切片转换为 Keyers 切片。

这很简单,只需遍历 []RequestObject 并将每个条目分配给类型为 []Keyer 的新条目。

另请参阅以下答案:

英文:

Define an interface:

type Keyer interface {
    Key() int // or whatever type the Key field has
}

Then implement the interface on both types:

func (r RequestObject) Key() int {
    return r.Key
}

func (r ResponseObject) Key() int {
    return r.Key
}

And rewrite your function to take this interface (and not use hungarian notation and endlessly long variable names):

func mergeKeyers(dst *[]Keyer, src []Keyer) {
    for _, s := range src {
        f := -1
        for i, d := range *dst {
            if s.Key() == d.Key() {
                f = i
                break
            }
        }
        if f == -1 {
            *dst = append(*dst, s)
        }
    }
}

Also, take into account Dave C's comment:

> you have an O(n×m) algorithm where you could use a O(n+m) one.

I'll leave it up to you to optimize your code in that way.

<hr>

Edit to address your second question:

The types *[]RequestObject and *[]Keyer are distinct and not interchangeable. What you need to do is convert your slice of RequestObjects to a slice of Keyers.

This is as easy as iterating over the []RequestObject and assigning each entry to a new entry in a value of type []Keyer.

See also these answers:

huangapple
  • 本文由 发表于 2015年8月18日 04:42:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/32059342.html
匿名

发表评论

匿名网友

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

确定