为什么golang中的list/ring类型使用额外的结构体Element/ring来处理单个项目而不是接口{}?我假设有一些好处,但我看不出来。
编辑:我的意思是问api,而不是关于在实现中使用元素/环。实现仍然可以使用非导出类型,但有api给出和接受接口{},那么为什么要让用户进出Element/Ring?
Edit2:作为一个例子,列表Back()函数可以像
func (l *List) Back() interface{} {
if l.len == 0 {
return nil
}
return l.root.prev.Value
}
列表内部仍然使用Element,但它将只是Element(未导出),因为它不会返回它,而只返回值
容器/列表是链表,所以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{}
}
container/ring不像你暗示的那样有一个"额外的"结构体。只有Ring结构体,它将一项链接到下一项/上一项,并保存值。没有开始/结束环,所以不需要有一个结构体作为一个整体对环进行操作,也不需要跟踪开始。
type Ring struct {
next, prev *Ring
Value interface{} // for use by client; untouched by this library
}
包含过滤或未导出的字段。
包列表
File 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{}
}
包环
File 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{}
,因为这没有意义。你不能在接口类型上使用方法。
Go编程语言规范
方法声明
方法是带有接收者的函数。方法声明绑定一个标识符(方法名)与方法关联,并关联该方法与接收者的基本类型。
MethodDecl = "func" Receiver MethodName ( Function | Signature ) . Receiver = "(" [ identifier ] [ "*" ] BaseTypeName ")" . BaseTypeName = identifier .
接收方类型必须是T或*T的形式,其中T是类型名。用T表示的类型称为接收基类型;它一定不是指针或接口类型和它必须以相同的方式声明包作为方法。该方法被称为绑定到基类型方法名只在该类型的选择器中可见。