glist (并发安全链表)

glist

带并发安全开关的双向列表。

使用场景 :

默认情况下为非并发安全,也可以开启并发安全特性来使用到并发安全场景中。

使用方式 :

import "github.com/gogf/gf/container/glist"

接口文档 :

https://godoc.org/github.com/gogf/gf/container/glist

性能测试

https://github.com/gogf/gf/blob/master/container/glist/glist_z_bench_test.go

goos: darwin
goarch: amd64
pkg: github.com/gogf/gf/container/glist
Benchmark_PushBack-4             5000000               268 ns/op              56 B/op          2 allocs/op
Benchmark_PushFront-4           10000000               435 ns/op              56 B/op          2 allocs/op
Benchmark_Len-4                 30000000              44.5 ns/op               0 B/op          0 allocs/op
Benchmark_PopFront-4            20000000              71.1 ns/op               0 B/op          0 allocs/op
Benchmark_PopBack-4             30000000              70.1 ns/op               0 B/op          0 allocs/op
PASS

使用示例

示例1,简单使用

package main

import (
    "fmt"
    "github.com/gogf/gf/container/glist"
)

func main() {
    // Not concurrent-safe in default.
    l := glist.New()
    // Push
    l.PushBack(1)
    l.PushBack(2)
    e := l.PushFront(0)
    // Insert
    l.InsertBefore(e, -1)
    l.InsertAfter(e, "a")
    fmt.Println(l)
    // Pop
    fmt.Println(l.PopFront())
    fmt.Println(l.PopBack())
    fmt.Println(l)
}

执行后,输出结果:

[-1,0,"a",1,2]
-1
2
[0,"a",1]

示例2,链表遍历

该示例中我们将通过读锁和写锁遍历一个并发安全的链表,分别通过RLockFunc和LockFunc实现。

package main

import (
    "container/list"
    "fmt"
    "github.com/gogf/gf/container/garray"
    "github.com/gogf/gf/container/glist"
)

func main() {
    // concurrent-safe list.
    l := glist.NewFrom(garray.NewArrayRange(1, 10, 1).Slice(), true)
    // iterate reading from head.
    l.RLockFunc(func(list *list.List) {
        length := list.Len()
        if length > 0 {
            for i, e := 0, list.Front(); i < length; i, e = i+1, e.Next() {
                fmt.Print(e.Value)
            }
        }
    })
    fmt.Println()
    // iterate reading from tail.
    l.RLockFunc(func(list *list.List) {
        length := list.Len()
        if length > 0 {
            for i, e := 0, list.Back(); i < length; i, e = i+1, e.Prev() {
                fmt.Print(e.Value)
            }
        }
    })

    fmt.Println()

    // iterate reading from head using IteratorAsc.
    l.IteratorAsc(func(e *glist.Element) bool {
        fmt.Print(e.Value)
        return true
    })
    fmt.Println()
    // iterate reading from tail using IteratorDesc.
    l.IteratorDesc(func(e *glist.Element) bool {
        fmt.Print(e.Value)
        return true
    })

    fmt.Println()

    // iterate writing from head.
    l.LockFunc(func(list *list.List) {
        length := list.Len()
        if length > 0 {
            for i, e := 0, list.Front(); i < length; i, e = i+1, e.Next() {
                if e.Value == 6 {
                    e.Value = "M"
                    break
                }
            }
        }
    })
    fmt.Println(l)
}

执行后,输出结果为:

12345678910
10987654321
12345678910
10987654321
[1,2,3,4,5,"M",7,8,9,10]

示例3,JSON序列化/反序列

glist容器实现了标准库json数据格式的序列化/反序列化接口。

  1. Marshal
 package main

 import (
     "encoding/json"
     "fmt"
     "github.com/gogf/gf/container/glist"
     "github.com/gogf/gf/frame/g"
 )

 func main() {
     type Student struct {
         Id     int
         Name   string
         Scores *glist.List
     }
     s := Student{
         Id:     1,
         Name:   "john",
         Scores: glist.NewFrom(g.Slice{100, 99, 98}),
     }
     b, _ := json.Marshal(s)
     fmt.Println(string(b))
 }

执行后,输出结果:

 {"Id":1,"Name":"john","Scores":[100,99,98]}
  1. Unmarshal
 package main

 import (
     "encoding/json"
     "fmt"
     "github.com/gogf/gf/container/glist"
 )

 func main() {
     b := []byte(`{"Id":1,"Name":"john","Scores":[100,99,98]}`)
     type Student struct {
         Id     int
         Name   string
         Scores *glist.List
     }
     s := Student{}
     json.Unmarshal(b, &s)
     fmt.Println(s)
 }

执行后,输出结果:

 {1 john [100,99,98]}