glist

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

使用场景

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

使用方式

  1. 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

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

使用示例

示例1,简单使用

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/gogf/gf/container/glist"
  5. )
  6. func main() {
  7. // Not concurrent-safe in default.
  8. l := glist.New()
  9. // Push
  10. l.PushBack(1)
  11. l.PushBack(2)
  12. e := l.PushFront(0)
  13. // Insert
  14. l.InsertBefore(e, -1)
  15. l.InsertAfter(e, "a")
  16. fmt.Println(l)
  17. // Pop
  18. fmt.Println(l.PopFront())
  19. fmt.Println(l.PopBack())
  20. fmt.Println(l)
  21. }

执行后,输出结果:

  1. [-1,0,"a",1,2]
  2. -1
  3. 2
  4. [0,"a",1]

示例2,链表遍历

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

  1. package main
  2. import (
  3. "container/list"
  4. "fmt"
  5. "github.com/gogf/gf/container/garray"
  6. "github.com/gogf/gf/container/glist"
  7. )
  8. func main() {
  9. // concurrent-safe list.
  10. l := glist.NewFrom(garray.NewArrayRange(1, 10, 1).Slice(), true)
  11. // iterate reading from head.
  12. l.RLockFunc(func(list *list.List) {
  13. length := list.Len()
  14. if length > 0 {
  15. for i, e := 0, list.Front(); i < length; i, e = i+1, e.Next() {
  16. fmt.Print(e.Value)
  17. }
  18. }
  19. })
  20. fmt.Println()
  21. // iterate reading from tail.
  22. l.RLockFunc(func(list *list.List) {
  23. length := list.Len()
  24. if length > 0 {
  25. for i, e := 0, list.Back(); i < length; i, e = i+1, e.Prev() {
  26. fmt.Print(e.Value)
  27. }
  28. }
  29. })
  30. fmt.Println()
  31. // iterate reading from head using IteratorAsc.
  32. l.IteratorAsc(func(e *glist.Element) bool {
  33. fmt.Print(e.Value)
  34. return true
  35. })
  36. fmt.Println()
  37. // iterate reading from tail using IteratorDesc.
  38. l.IteratorDesc(func(e *glist.Element) bool {
  39. fmt.Print(e.Value)
  40. return true
  41. })
  42. fmt.Println()
  43. // iterate writing from head.
  44. l.LockFunc(func(list *list.List) {
  45. length := list.Len()
  46. if length > 0 {
  47. for i, e := 0, list.Front(); i < length; i, e = i+1, e.Next() {
  48. if e.Value == 6 {
  49. e.Value = "M"
  50. break
  51. }
  52. }
  53. }
  54. })
  55. fmt.Println(l)
  56. }

执行后,输出结果为:

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

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

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

  1. Marshal

    1. package main
    2. import (
    3. "encoding/json"
    4. "fmt"
    5. "github.com/gogf/gf/container/glist"
    6. "github.com/gogf/gf/frame/g"
    7. )
    8. func main() {
    9. type Student struct {
    10. Id int
    11. Name string
    12. Scores *glist.List
    13. }
    14. s := Student{
    15. Id: 1,
    16. Name: "john",
    17. Scores: glist.NewFrom(g.Slice{100, 99, 98}),
    18. }
    19. b, _ := json.Marshal(s)
    20. fmt.Println(string(b))
    21. }

    执行后,输出结果:

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

    1. package main
    2. import (
    3. "encoding/json"
    4. "fmt"
    5. "github.com/gogf/gf/container/glist"
    6. )
    7. func main() {
    8. b := []byte(`{"Id":1,"Name":"john","Scores":[100,99,98]}`)
    9. type Student struct {
    10. Id int
    11. Name string
    12. Scores *glist.List
    13. }
    14. s := Student{}
    15. json.Unmarshal(b, &s)
    16. fmt.Println(s)
    17. }

    执行后,输出结果:

    1. {1 john [100,99,98]}