在编写两种方法(一种用于切片,一种用于字符串映射)时,我意识到这两种方法的实现是相同的,唯一改变的是函数的原型。
我试图避免重复它,最初我想到了以下内容(参见 FIXME 部分):
package main
import (
"fmt"
"strings"
)
type SomethingList []*Something
type SomethingMap map[string]*Something
type Something struct {
ID string
Type int
}
func (sl SomethingList) GetIDsString() string {
return getIDsString(sl)
}
func (sm SomethingMap) GetIDsString() string {
return getIDsString(sm)
}
func getIDsString(elements interface{}) string {
var ids []string
// FIXME: Yes, I know I can't iterate over an interface
for element = range elements {
ids = append(ids, element.ID)
}
return strings.Join(ids, ",")
}
func main() {
s1 := Something{ID: "ABC", Type: 1}
s2 := Something{ID: "DEF", Type: 1}
sl := SomethingList{&s1, &s2}
sm := SomethingMap{s1.ID: &s1, s2.ID: &s2}
fmt.Println(sl.GetIDsString())
fmt.Println(sm.GetIDsString())
}
重要的部分是函数getIDsString
,它基本上采用结构的 ID 字段并将其内容连接到切片或映射的所有成员中。
在阅读了一些关于接口如何工作的信息后,我现在意识到(是的,我是 Go 的新手,这可能已经很明显了 :-))这是行不通的,因为 Go 是静态类型的,我不能简单地在运行时更改类型。接口也不允许我迭代。我已经能够使用一个循环来接近,该循环使用 reflect.ValueOf 和 Index() 上的 Len() 方法进行迭代以访问每个元素。但是 Index() 不适用于字符串映射。
在不复制大量代码的情况下解决这个问题的最惯用的方法是什么?
谢谢!