首先是环形链表的结构与初初始化
type Ring struct {next, prev *RingValue interface{} // for use by client; untouched by this library
}func (r *Ring) init() *Ring {r.next = rr.prev = rreturn r
}
环形链表是有n个带前后指针的节点形成的,他可以正序也可以倒序遍历。
他的初始化是指定一个节点,然后把next和prev都指向自己。
然后是新建一个双向环形链表,传入一个长度,返回链表指针。该链表里面的节点都是空的,可以存放任何东西(因为是空接口)
func New(n int) *Ring {if n <= 0 {return nil}r := new(Ring)p := rfor i := 1; i < n; i++ {p.next = &Ring{prev: p}p = p.next}p.next = rr.prev = preturn r
}
他的Next() 和 prev()方法也很简单,返回他后一个元素和前一个元素的指针。
// Next returns the next ring element. r must not be empty.
func (r *Ring) Next() *Ring {if r.next == nil {return r.init()}return r.next
}// Prev returns the previous ring element. r must not be empty.
func (r *Ring) Prev() *Ring {if r.next == nil {return r.init()}return r.prev
}
move方法。只是简单的指针移动
func (r *Ring) Move(n int) *Ring {if r.next == nil {return r.init()}switch {case n < 0:for ; n < 0; n++ {r = r.prev}case n > 0:for ; n > 0; n-- {r = r.next}}return r
}
假设当前指针指向1,顺时针方向为next方向,则move(1),就是把指针移到2位置,move(-1),就是把指针移到7位置
获取长度(注意for循环里第二个条件p!=r,判断是否是遍历的起始节点)
func (r *Ring) Len() int {n := 0if r != nil {n = 1for p := r.Next(); p != r; p = p.next {n++}}return n
}
do方法是传入一个方法,然后让每个节点都去运行这个方法
func (r *Ring) Do(f func(interface{})) {if r != nil {f(r.Value)for p := r.Next(); p != r; p = p.next {f(p.Value)}}
}
link是吧两个不同的环形链表连接起来,如果r和s在同一个环形链表里,则会把r与s之间沿着next方向的元素移除。
unc (r *Ring) Link(s *Ring) *Ring {n := r.Next()if s != nil {p := s.Prev()// Note: Cannot use multiple assignment because// evaluation order of LHS is not specified.r.next = ss.prev = rn.prev = pp.next = n}return n
}
unlick是把当前节点之后的n个节点移除,调用的是link方法,原理可以参考上图同一个环形链表的link方法
func (r *Ring) Unlink(n int) *Ring {if n <= 0 {return nil}return r.Link(r.Move(n + 1))
}
应用场景:
交易所的历史成交交易。可以存在环形链表里,当有新的交易成交时,把指针像下移一个,然后把旧的成交订单替换掉。(这边只是在内存里存了一定数量的最新成交订单,所有会有覆盖的情况,当链表长度为50,此时有新的成交订单进来时,会把最旧的那个订单替换掉)
r := this.currentMtf.Next()
r.Value = mtfthis.currentMtf = r
查询历史订单
//do方法链上每个节点都会执行。这边做的只是封装工作,和重点无关,同时,这边像next方向,
//把成交订单添加入items。但是当前指针的订单是最新的,currentMtf.Next()就是最旧的订单或者nil
//所有items是按旧到新排序
match.currentMtf.Next().Do(func(data interface{}) {if data != nil {mtf := data.(*msq.MtfData)item := TradeItem{mtf.MatchTime, mtf.Price, mtf.Amount, mtf.IsBuy}items = append(items, item)}
})//因为要显示的订单成交情况是最新的订单再到旧的,所有再次把他数据倒过来
for i := len(items) - 1; i >= 0; i-- {depth--info.Trades = append(info.Trades, items[i])if depth == 0 {break}
}