Go中的仿制药会是什么?

时间:2014-01-17 21:22:58

标签: go

最近有很多关于Golang的批评,因为它不支持泛型。这到底是什么意思呢?您如何向来自像Ruby这样的动态类型语言的人解释这一点,这不是一个熟悉的概念?

2 个答案:

答案 0 :(得分:6)

在动态类型语言中,您不关心它是什么类型的列表,只是它是一个列表。但是,在静态类型语言中,您确实关心它是什么类型的列表,因为类型是“A的列表”,其中“A”是某种类型。也就是说,list Alist B的类型不同。

因此,当您谈到泛型时,使用A -> B调用列表中foreach类型的某个函数意味着该列表必须是list A。但是......如果你使用泛型,那么你不必声明A是什么,你可以在以后填写它。因此,您建立了一个合同,其中给定list C和函数A -> BA === C以便编译。这大大减少了样板。

在Go中,由于缺乏泛型和声明这种类型合同的能力,你必须编写一个函数,该函数在int列表,double列表,字符串列表等上运行。你可以'只是以“通用”的方式定义事物。

答案 1 :(得分:2)

William B. Yager blog post提醒为什么Go中存在的“通用”部分是不够的:

  

您可以轻松编写通用功能   假设您想编写一个函数,该函数为可以进行哈希处理的对象打印哈希码。您可以定义一个允许您使用静态类型安全保证执行此操作的接口,如下所示:

type Hashable interface {
  Hash() []byte
}

func printHash(item Hashable) {
   fmt.Println(item.Hash())
}
  

现在,您可以向Hashable提供任何printHash对象,并且您还可以获得静态类型检查。这很好。

     

如果您想编写通用数据结构怎么办?   让我们写一个简单的链表。在Go中编写通用数据结构的惯用方法是:

(这只是一个开始)

type LinkedList struct {
   value interface{}
   next *LinkedList
}

func (oldNode *LinkedList) prepend(value interface{}) *LinkedList {
   return &LinkedList{value, oldNode}
}
  

在Go中构建通用数据结构的“正确”方法是将内容转换为顶级类型,然后将它们放入数据结构中。这就是Java过去常常工作的方式,大约在2004年。然后人们意识到这完全打败了类型系统的目的

     

如果您拥有这样的数据结构,则可以完全消除类型系统提供的任何好处。例如,这是完全有效的代码:

node := tail(5).prepend("Hello").prepend([]byte{1,2,3,4}) 

这就是为什么,如果你想保留类型系统的好处,你必须使用一些代码生成来生成特定类型的boileplate代码。

gen project 就是这种做法的一个例子:

  

gen在开发时使用命令行为您的类型生成代码   gen不是导入;生成的源成为项目的一部分,不需要外部依赖。


2017年6月更新:Dave Cheney详细介绍了Generics for Go在他的文章“Simplicity Debt”和“Simplicity Debt Redux”中的含义。

Go 2.0 is now actively discussed at the core team level以来,Dave指出了泛型所涉及的内容,即:

  • 错误处理:Generic允许monadic Error handling,这意味着您需要了解其余的monad:启用处理计算管道而不是在每次函数调用后检查错误。<登记/> 但是:你需要了解monad!
  • 集合:方便自定义集合类型,无需使用interface {}装箱和类型断言。
    但这留下了如何处理内置切片和地图类型的问题。
  • 切片:它是否会消失,如果是这样,会如何影响常见操作,例如处理调用io.Reader.Read的结果? 如果切片没有消失,是否需要添加运算符重载,以便用户定义的集合类型可以实现切片运算符?
  • 向量:Go的Pascal类数组类型在编译时具有固定的大小。如何在不诉诸不安全黑客的情况下实现可增长的矢量?
  • 迭代器:您真正希望能够做的是组合数据库结果和网络请求的迭代器。
    简而言之,来自流程外部的数据 - 当数据在您的流程之外时,检索它可能会失败 在这种情况下,您可以选择,Iterable接口是否返回值,值和错误,或者您可以选择类型路径。
  • 不变性:将函数参数标记为const的能力不足,因为虽然它限制接收者改变值,但它并不禁止调用者这样做,是我今天在Go节目中看到的大部分数据竞赛 也许Go需要的不是不变性,而是所有权语义。

由于Russ Cox在“My Go Resolutions for 2017”中写道:

  

今天,还有更新的尝试,包括Dart,Midori,Rust和Swift。

最新讨论是Go issue 15292:它还引用了“Summary of Go Generics Discussions”。