Go组件库总结之介入式链表
本篇文章我们用Go封装一个介入式的双向链表,目的是将链表的实现和具体元素解耦。文章参考自:https://github.com/brewlin/net-protocol
1.元素的接口
type Element interface {
Next() Element
Prev() Element
SetNext(Element)
SetPrev(Element)
}
2.链表的封装
type List struct {
head Element
tail Element
}
3.链表的操作
// Reset 清空List
func (l *List) Reset() {
l.head = nil
l.tail = nil
}
// Empty 判断List是否为空
func (l *List) Empty() bool {
return l.head == nil
}
// Front 返回第一个元素
func (l *List) Front() Element {
return l.head
}
// Back 返回最后一个元素
func (l *List) Back() Element {
return l.tail
}
// PushFront 插入元素到列头
func (l *List) PushFront(e Element) {
e.SetNext(l.head)
e.SetPrev(nil)
if l.head != nil {
l.head.SetPrev(e)
} else {
l.tail = e
}
l.head = e
}
// PushBack 插入元素到列尾
func (l *List) PushBack(e Element) {
e.SetNext(nil)
e.SetPrev(l.tail)
if l.tail != nil {
l.tail.SetNext(e)
} else {
l.head = e
}
l.tail = e
}
// PushBackList 插入一个list到列尾,并清空这个list
func (l *List) PushBackList(m *List) {
if l.head == nil {
l.head = m.head
l.tail = m.tail
} else if m.head != nil {
l.tail.SetNext(m.head)
m.head.SetPrev(l.tail)
l.tail = m.tail
}
m.head = nil
m.tail = nil
}
// InsertAfter 在b后插入e
func (l *List) InsertAfter(b, e Element) {
a := b.Next()
e.SetNext(a)
e.SetPrev(b)
b.SetNext(e)
if a != nil {
a.SetPrev(e)
} else {
l.tail = e
}
}
// InsertBefore 在a前插入e
func (l *List) InsertBefore(a, e Element) {
b := a.Prev()
e.SetNext(a)
e.SetPrev(b)
a.SetPrev(e)
if b != nil {
b.SetNext(e)
} else {
l.head = e
}
}
// Remove 移除e
func (l *List) Remove(e Element) {
prev := e.Prev()
next := e.Next()
if prev != nil {
prev.SetNext(next)
} else {
l.head = next
}
if next != nil {
next.SetPrev(prev)
} else {
l.tail = prev
}
}
4.元素接口的实现
type Entry struct {
next Element
prev Element
}
func (e *Entry) Next() Element {
return e.next
}
func (e *Entry) Prev() Element {
return e.prev
}
func (e *Entry) SetNext(elem Element) {
e.next = elem
}
func (e *Entry) SetPrev(elem Element) {
e.prev = elem
}
5.使用示例
我们只需在结构体中用匿名字段继承Entry,就可以将其作为链表上的元素进行插入删除操作。
type Card struct {
Entry
num int
}
func main() {
var list List
for i := 0; i < 10; i++ {
list.PushBack(&Card{num:i})
}
for !list.Empty() {
e := list.Front()
fmt.Println(e.(*Card).num)
list.Remove(e)
}
}