为什么golang list/Ring使用元素和环结构?

为什么golang list/Ring使用元素和环结构?,list,go,List,Go,为什么golang中的列表/环类型对单个项使用额外的structs元素/环,而不是接口{}?我假设有一些好处,但我看不到 编辑:我的意思是询问api,而不是在实现中使用元素/环。实现仍然可以使用未导出的类型,但是api提供并获取接口{},那么为什么要让用户进出元素/环呢 Edit2:举个例子,list Back()函数可以是 func (l *List) Back() interface{} { if l.len == 0 { return nil } r

为什么golang中的列表/环类型对单个项使用额外的structs元素/环,而不是接口{}?我假设有一些好处,但我看不到

编辑:我的意思是询问api,而不是在实现中使用元素/环。实现仍然可以使用未导出的类型,但是api提供并获取接口{},那么为什么要让用户进出元素/环呢

Edit2:举个例子,list Back()函数可以是

func (l *List) Back() interface{} {
    if l.len == 0 {
        return nil
    }
    return l.root.prev.Value
}

列表在内部仍然使用元素,但它只是元素(未报告),因为它不会返回元素,而只返回值。

它们包含筛选字段或未报告字段


文件:


文件:


显然,
元素
的类型不能是
接口{}
,因为这没有意义。接口类型上不能有方法

方法是带有接收器的函数。方法声明绑定 标识符(方法名称)与方法关联,并将该方法关联 与接收器的基本类型

MethodDecl   = "func" Receiver MethodName ( Function | Signature ) .
Receiver     = "(" [ identifier ] [ "*" ] BaseTypeName ")" .
BaseTypeName = identifier .
接收方类型必须为T或*T格式,其中T是类型名称。 用T表示的类型称为接收器基类型;不应该这样 指针或接口类型,并且必须在同一个 包作为方法。该方法被称为绑定到基类型 方法名称仅在该类型的选择器中可见


容器/列表是链表,因此使用
list
struct可以作为一个整体对列表进行操作,并跟踪列表的开头和结尾,这将是有益的

因为它是一个链接列表,所以您希望能够将项目链接在一起,并从一个项目导航到下一个或上一个项目。这需要一个结构,该结构包含指向下一个和上一个项的指针,并允许您导航到这些项(使用next()和Prev()函数)。
元素
结构就是为了达到这个目的,它包含指向下一个/上一个项目的指针和实际值

下面是如何定义结构的,它们也有不同的成员函数

type List struct {
    root Element // sentinel list element, only &root, root.prev, and root.next are used
    len  int     // current list length excluding (this) sentinel element
}

type Element struct {
    // Next and previous pointers in the doubly-linked list of elements.
    // To simplify the implementation, internally a list l is implemented
    // as a ring, such that &l.root is both the next element of the last
    // list element (l.Back()) and the previous element of the first list
    // element (l.Front()).
    next, prev *Element

    // The list to which this element belongs.
    list *List

    // The value stored with this element.
    Value interface{}
}
容器/环没有您所暗示的“额外”结构。只有环结构将一个项链接到下一个/上一个项,并且还保存该值。环没有起点/终点,因此不需要一个结构作为一个整体在环上运行或跟踪起点

type Ring struct {
    next, prev *Ring
    Value      interface{} // for use by client; untouched by this library
}

@cellige在这种情况下,你是如何以合理的方式获得下一个/上一个项目的?如果您在某个节点上,并且想要获得下一个节点,则必须将“current”值传递给列表。列表实现必须线性扫描列表才能找到包含“当前”值的元素并返回其下一个指针,这非常可怕。@否:实现不需要线性扫描任何内容。它可以查看未报告的字段,并直接使用这些字段获取下一个或上一个节点。@否:环结构使用环结构上的方法公开下一个和上一个指针。这允许实现确保没有人以破坏容器不变量的方式更改指针。@KenBloom我说的是OP希望API直接获取接口{},这听起来像是他希望直接处理值,而不是包装值的结构。(或者更确切地说,如果接口{}实际上只是一个元素,那么处理接口{}而不是元素有什么意义呢?)Yes@nos的意思是正确的。我想知道为什么他们让用户处理元素中的值,而不仅仅是返回接口{}并为推送函数获取接口{}。仍然在内部使用元素跟踪指针。@cellige:它没有澄清。用代码给出一个具体的例子,说明你想做什么以及它应该如何工作。您的API外观和工作方式如何?示例位于顶部,先生!
type List struct {
    root Element // sentinel list element, only &root, root.prev, and root.next are used
    len  int     // current list length excluding (this) sentinel element
}

type Element struct {
    // Next and previous pointers in the doubly-linked list of elements.
    // To simplify the implementation, internally a list l is implemented
    // as a ring, such that &l.root is both the next element of the last
    // list element (l.Back()) and the previous element of the first list
    // element (l.Front()).
    next, prev *Element

    // The list to which this element belongs.
    list *List

    // The value stored with this element.
    Value interface{}
}
type Ring struct {
    next, prev *Ring
    Value      interface{} // for use by client; untouched by this library
}