我正在编写一些数据结构,以便让我的脚湿透,并了解Go语言,并且正在努力解决Go缺乏的泛型问题。
在我的实现中,我选择强制每个用户实现一个接口,所以我的结构可以抽象地引用这些对象,但我不喜欢我的解决方案,因为这不会在编译时验证,如你所见。
容器中保存的每个对象都必须实现以下签名的Compare
函数(如果你想要保留的只是原始类型,那就很麻烦)
type Comparer interface {
Compare(Comparer) int
}
然后,您可以拥有实现接口的各种元素,如float64
或自定义结构:
type number float64
func (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
}
这里的问题是我无法比较Person
和number
。我意识到我可以在运行时检查类型,但我想找到a)编译时验证类型的方法或b)一般实现数据结构的不同方法。
问题
答案 0 :(得分:2)
我的意思是代码没有什么不安全的......没有编译时安全性。例如,在下面的方法中,第一行在comparer
上执行类型断言,如果它不是数字而你没有_
用于LHS上的第二项,那么它将返回错误,你可以采取相应的行动。或者你可以在没有它的情况下调用它,并且会发生panic
将它留给调用者来处理它(因为他们是用错误的参数调用方法的人,就像得到一个{在C#中{1}}。
InvalidOperationException
这与C#之类的语言之间的区别仅仅在于泛型,它允许您以更快的编译时间来执行这些类型的事情(因为您无法正确调用该方法)。话虽这么说,有一段时间C#之前有泛型和许多语言,但根本没有它们。这些操作并不比你常规执行的强制转换更不安全,即使在 具有泛型的语言中也是如此。