我正在编写一些数据结构来让我的脚弄湿并学习 Go 语言,并且正在为 Go 缺乏泛型而苦苦挣扎。在我的实现中,我选择强制每个用户实现一个接口,以便我的结构可以抽象地引用这些对象,但我不喜欢我的解决方案,因为正如您将看到的那样,这在编译时没有得到验证。比较器接口保存在容器中的每个对象都必须实现Compare以下签名的函数(如果您只想保存原始类型,则很麻烦)type Comparer interface { Compare(Comparer) int}然后,您可以拥有实现接口的各种元素,例如float64或自定义结构:浮动64type number float64func (n1 number) Compare(comparer Comparer) int { n2, _ := comparer.(number) if n1 > n2 { return 1 } else if n1 < n2 { return -1 } else { return 0 }}人type Person struct { Age int}func (p1 Person) Compare(comparer Comparer) int { p2, _ := comparer.(Person) if p1.Age > p2.Age { return 1 } else if p1.Age < p2.Age { return -1 } else { return 0 }}现在我可以比较其中的一些东西:func main() { fmt.Println(number(2).Compare(number(4))) // -1 fmt.Println(Person{26}.Compare(Person{28})) // -1 fmt.Println(Person{26}.Compare(number(28))) // 1}这里的问题是我不应该比较 aPerson和 a number。我意识到我可以在运行时检查类型,但我想找到 a) 一种验证类型的编译时方法或 b) 一种不同的方法来通用地实现数据结构。问题我知道使用内置数据结构几乎可以做任何可能需要的事情……但是如果没有泛型或运行时类型检查,人们如何制作自己的数据结构呢?由于 Go 中的接口实现似乎使用了鸭子类型,那么 Go 在编译时如何强制类型?
1 回答
白板的微信
TA贡献1883条经验 获得超3个赞
我的意思是该代码没有任何不安全的地方......只是没有编译时安全。例如,在您下面的方法中,第一行对 进行类型断言comparer,如果它不是数字并且您没有_LHS 上的第二项,那么它将返回一个错误,您可以采取相应的行动。或者你可以在没有它的情况下调用它,并且panic会发生将它留给调用者来处理它(这很合适,因为他们是用错误的参数调用方法的人,就像InvalidOperationException在 C# 中得到一个一样)。
func (n1 number) Compare(comparer Comparer) int {
n2, _ := comparer.(number)
if n1 > n2 {
return 1
} else if n1 < n2 {
return -1
} else {
return 0
}
}
这与像 C# 这样的语言之间的区别纯粹在于泛型,它允许您以更高的编译时安全性来执行这些类型的事情(因为您不能错误地调用该方法)。话虽如此,在 C# 有泛型之前有一段时间,而在此之前的许多语言根本没有它们。即使在具有泛型的语言中,这些操作也不会比您经常进行的转换更不安全。
- 1 回答
- 0 关注
- 168 浏览
添加回答
举报
0/150
提交
取消