为什么golang中的列表/环类型对单个项使用额外的结构元素/环而不是接口{}?我假设有一些好处,但我看不到它。
编辑:我想询问api而不是关于在实现中使用Element / Ring的问题。实现仍然可以使用非导出类型,但是api给出并接受接口{},那么为什么要让用户进出Element / Ring?
Edit2:作为示例,Back()函数列表可能类似于
func (l *List) Back() interface{} {
if l.len == 0 {
return nil
}
return l.root.prev.Value
}
列表仍在内部使用Element,但它只是元素(未导出),因为它不会返回它,但只返回值。
答案 0 :(得分:4)
容器/列表是链接列表,因此拥有List
结构可以对整个列表进行操作并跟踪列表的开头和结尾是有益的。
由于它是链接列表,您希望能够将项目链接在一起并从一个项目导航到下一个项目或上一个项目。这需要一个结构,该结构保存指向下一个和前一个项目的指针,并允许您导航到这些项目(使用Next()和Prev()函数)。 Element
结构用于此目的,它包含指向下一个/上一个项目的指针以及实际值。
以下是结构的定义方式,它们也有各种成员函数
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{}
}
容器/环没有你所暗示的“额外”结构。只有Ring结构将一个项链接到下一个/上一个项并且还保存该值。 Ring没有开始/结束,因此不需要在整个环上运行结构或跟踪开始。
type Ring struct {
next, prev *Ring
Value interface{} // for use by client; untouched by this library
}
答案 1 :(得分:3)
它们包含已过滤或未导出的字段。
档案list.go
:
// Package list implements a doubly linked list.
// Element is an element of a linked list.
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{}
}
档案ring.go
:
// Package ring implements operations on circular lists.
// A Ring is an element of a circular list, or ring.
// Rings do not have a beginning or end; a pointer to any ring element
// serves as reference to the entire ring. Empty rings are represented
// as nil Ring pointers. The zero value for a Ring is a one-element
// ring with a nil Value.
//
type Ring struct {
next, prev *Ring
Value interface{} // for use by client; untouched by this library
}
显然,Element
和Ring
的类型不能interface{}
,因为它没有任何意义。您无法在接口类型上使用方法。
The Go Programming Language Specification
方法是具有接收器的功能。方法声明绑定一个 标识符,方法名称,方法,并关联方法 使用接收器的基本类型。
MethodDecl = "func" Receiver MethodName ( Function | Signature ) . Receiver = "(" [ identifier ] [ "*" ] BaseTypeName ")" . BaseTypeName = identifier .
接收器类型必须是T或* T形式,其中T是类型名称。 由T表示的类型称为接收器基类型;一定不是 指针或接口类型,必须在同一个声明 包作为方法。据说该方法与基类型绑定 并且方法名称仅在该类型的选择器中可见。