继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

golang list使用

aluckdog
关注TA
已关注
手记 499
粉丝 70
获赞 400

最近需要使用到一个Queue队列, 并发写入的.
作为gopher, 第一个马上想到的是channel, channel用起来是很爽, 并发安全, 直接一端取, 一端塞, 非常和谐友好. 但是, channel不支持动态扩容啊, 当一个channel满了之后, 想要扩容, 只能make一个新的, 然后做一个迁移, 这会卡住好长时间, 业务需求不满足.
然后找到了container/list这个包, 有个list结构体, 使用简单, 接口清晰, 代码实现也简单, 用着也挺舒服的. 就是不是并发安全的, 只能自己动手包了一层并发的皮:

import (    "container/list"
    "sync")

type Queue struct {
    l *list.List
    m sync.Mutex
}func NewQueue() *Queue {    return &Queue{l: list.New()}
}

func (q *Queue) PushBack(v interface{}) {    if v == nil {        return
    }
    q.m.Lock()
    defer q.m.Unlock()
    q.l.PushBack(v)
}

func (q *Queue) Front() *list.Element {
    q.m.Lock()
    defer q.m.Unlock()    return q.l.Front()
}

func (q *Queue) Remove(e *list.Element) {    if e == nil {        return
    }
    q.m.Lock()
    defer q.m.Unlock()
    q.l.Remove(e)
}

func (q *Queue) Len() int {
    q.m.Lock()
    defer q.m.Unlock()    return q.l.Len()
}

这样就基本满足了.

使用过程中, 发现list有个小坑: 遍历的时候不能Remove

for e := l.Front(); e != nil; e = e.Next {
    l.Remove(e)
}

按照设想, 这应该会移除list里所有的元素, 但是, 结果是只移除了第一个. 原因是: Remove时候, e.next = nil, 使得for判断中, e != nil不成立了, 所以退出了循环.
这时候有两种解决办法:

var next *list.Elementfor e := l.Front(); e != nil; e = next {    next = e.Next()
    l.Remove(e)
}
for {    e := l.Front()
    if e == nil {
            break
    }    l.Remove(e)
}

that's all



作者:Lucas_Ye
链接:https://www.jianshu.com/p/dfd6e5779f4b

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP