Go 编程语言中的任何类型和实现通用列表

Posted

技术标签:

【中文标题】Go 编程语言中的任何类型和实现通用列表【英文标题】:Any type and implementing generic list in go programming language 【发布时间】:2011-10-12 15:34:50 【问题描述】:

我正在尝试go programming language。

我对 Go 的简单性感到兴奋,但在玩过它之后我遇到了一些麻烦。

1 .我知道 Go 不支持泛型和继承。 有没有办法实现泛型列表?

我正在考虑使用:

type Any interface  

但是如何检查该值是否为 NULL。 我正在寻找与 C 等效的实现

struct List 
  List* tail;
  void* head;

或者使用代数数据类型:

data List a = Nil | Cons a (List a)

2.更高级的要求是为具有特定类型字段的对象制作一些容器? 例如,在 Scala 编程语言中,我可以输入:

val List[Animal  type SuitableFood = Grass ]

获取Animals 中的List,其成员类型为SuitableFood,即Grass

【问题讨论】:

【参考方案1】:

您可以拥有interface 类型的元素列表。你可以放入任何元素,当你取出它时,你必须转换回你想要的类型。这就像您在 C 示例中所做的 void * 一样;并且还喜欢泛型之前的 Java 中的列表,以及没有泛型的 Objective-C 中的列表。 Go 库中的所有容器都执行此操作。

没有泛型,就没有元素类型的编译时检查。

如果你真的想要,你可以实现元素类型的运行时检查,通过使用反射来获取元素类型并根据预期类型检查它们。但是,这可能是矫枉过正。

【讨论】:

【参考方案2】:

我知道 Go 不支持泛型 [...]

从 Go 1.18 开始。我希望标准库最终会在当前的 container/list 包中添加通用容器,这样您就不必重新发明***了。

无论如何,作为一个思考练习,您可以复制标准 list.List 并自己添加类型参数:

type Element[T any] struct 
    next, prev  *Element[T]
    list        *List[T]
    Value       T


type List[T any] struct 
    root Element[T]
    len  int


// simplified constructor
func New[T any]() *List[T]  
    l := new(List[T])
    l.root.next = &l.root
    l.root.prev = &l.root
    l.len = 0
    return l

如您所见,Element struct 可以有一个 Element 类型的字段,但类型参数必须相同且顺序相同 (source)。

为具有特定类型字段的对象制作一些容器?

您可以通过将约束any 替换为指定所需方法的接口约束来做到这一点,例如:

type Animal interface  
    SuitableFood() string 


type Element[T Animal] struct 
    // ...

这将类型参数限制为那些实现Animal 接口的参数。


您可以做的是将类型参数限制为具有特定的字段1。如果您必须强制 T 具有特定值,则可以改为向接口约束添加更具体的方法,例如SuitableFoodGrass() 但这是一个泄漏抽象。接口模型行为,你应该坚持这个原则。


1:从技术上讲,您可以使用带有结构的类型约束,但它不是很有用

【讨论】:

以上是关于Go 编程语言中的任何类型和实现通用列表的主要内容,如果未能解决你的问题,请参考以下文章

Go 中的通用编程?

Go语言学习之旅--接口

Go语言学习之旅--接口

Go语言学习之旅--接口

go语言之数组

Go语言接口规则