以下常用方法列表,文档更新可能滞后于代码新特性,更多的方法及示例请参考代码文档:https://pkg.go.dev/github.com/gogf/gf/v2/container/gring

New

  • 说明:New创建并返回cap元素的环形结构。可选参数safe指定是否在并发安全中使用此结构,默认情况下为false

  • 格式:

    New(cap int, safe ...bool) *Ring
  • 示例:

    func ExampleNew() {
    	// Non concurrent safety
    	gring.New(10)
    
    	// Concurrent safety
    	gring.New(10, true)
    
    	// Output:
    }

Val

  • 说明:Val返回当前位置的值。
  • 格式:

    Val() interface{}
  • 示例:
    func ExampleRing_Val() {
    	r := gring.New(10)
    	r.Set(1)
    	fmt.Println("Val:", r.Val())
    
    	r.Next().Set("GoFrame")
    	fmt.Println("Val:", r.Val())
    
    	// Output:
    	// Val: 1
    	// Val: GoFrame
    }

Len

  • 说明:Len返回Ring的大小。
  • 格式:

    Len() int
  • 示例:

    func ExampleRing_Len() {
    	r1 := gring.New(10)
    	for i := 0; i < 5; i++ {
    		r1.Set(i).Next()
    	}
    	fmt.Println("Len:", r1.Len())
    
    	r2 := gring.New(10, true)
    	for i := 0; i < 10; i++ {
    		r2.Set(i).Next()
    	}
    	fmt.Println("Len:", r2.Len())
    
    	// Output:
    	// Len: 5
    	// Len: 10
    }

Cap

  • 说明:Cap返回Ring的容量。
  • 格式:

    Cap() int
  • 示例:

    func ExampleRing_Cap() {
    	r1 := gring.New(10)
    	for i := 0; i < 5; i++ {
    		r1.Set(i).Next()
    	}
    	fmt.Println("Cap:", r1.Cap())
    
    	r2 := gring.New(10, true)
    	for i := 0; i < 10; i++ {
    		r2.Set(i).Next()
    	}
    	fmt.Println("Cap:", r2.Cap())
    
    	// Output:
    	// Cap: 10
    	// Cap: 10
    }

Set

  • 说明:Set将为当前位置的值设置为Value
  • 格式:

    Set(value interface{}) *Ring
  • 示例:

    func ExampleRing_Set() {
    	r := gring.New(10)
    	r.Set(1)
    	fmt.Println("Val:", r.Val())
    
    	r.Next().Set("GoFrame")
    	fmt.Println("Val:", r.Val())
    
    	// Output:
    	// Val: 1
    	// Val: GoFrame
    }

Put

  • 说明:Put将为当前位置的值设置为Value,并将ring移动到下一个位置。
  • 格式:

    Put(value interface{}) *Ring
  • 示例:

    func ExampleRing_Put() {
    	r := gring.New(10)
    	r.Put(1)
    	fmt.Println("Val:", r.Val())
    	fmt.Println("Val:", r.Prev().Val())
    
    	// Output:
    	// Val: <nil>
    	// Val: 1
    }

Move

  • 说明:正向或者逆向移动n % r.Len()个节点,并返回移动后指向的位置。n>=0时,为正向移动,反之为反向移动。
  • 格式:

    Move(n int) *Ring
  • 示例:

    func ExampleRing_Move() {
    	r := gring.New(10)
    	for i := 0; i < 10; i++ {
    		r.Set(i).Next()
    	}
    	// ring at Pos 0
    	fmt.Println("CurVal:", r.Val())
    
    	r.Move(5)
    
    	// ring at Pos 5
    	fmt.Println("CurVal:", r.Val())
    
    	// Output:
    	// CurVal: 0
    	// CurVal: 5
    }

Prev

  • 说明:Prev返回ring上一个位置的元素。
  • 格式:

    Prev() *Ring
  • 示例:

    func ExampleRing_Prev() {
    	r := gring.New(10)
    	for i := 0; i < 5; i++ {
    		r.Set(i).Next()
    	}
    
    	fmt.Println("Prev:", r.Prev().Val())
    	fmt.Println("Prev:", r.Prev().Val())
    
    	// Output:
    	// Prev: 4
    	// Prev: 3
    }

Next

  • 说明:Next 返回ring下一个位置的元素。
  • 格式:

    Next() *Ring
  • 示例:

    func ExampleRing_Next() {
    	r := gring.New(10)
    	for i := 5; i > 0; i-- {
    		r.Set(i).Prev()
    	}
    
    	fmt.Println("Prev:", r.Next().Val())
    	fmt.Println("Prev:", r.Next().Val())
    
    	// Output:
    	// Prev: 1
    	// Prev: 2
    }

Link

  • 说明:
  • 1. Linkring rring s连接起来,使r.Next()变为s并返回r.Next()的原始值。r不能为空。Link后,ring rLenCap会变为原始rsLenCap之和。
  • 2. 如果rs指向同一个ring,则连接它们将从ring中删除rs之间的元素。移除的元素形成一个子ring,结果是对该子ring的引用(如果没有移除任何元素,则结果仍然是r.Next()的原始值,而不是nil)。
  • 3. 如果rs指向不同的ring,则连接它们将创建一个ring,其中s的元素插入r之后。结果指向插入后s的最后一个元素后面的元素。
  • 格式:

    (r *Ring) Link(s *Ring) *Ring
  • 示例:

    func ExampleRing_Link_Common() {
    	r := gring.New(10)
    	for i := 0; i < 5; i++ {
    		r.Set(i).Next()
    	}
    
    	s := gring.New(10)
    	for i := 0; i < 10; i++ {
    		val := i + 5
    		s.Set(val).Next()
    	}
    
    	r.Link(s) // Link Ring s to Ring r
    
    	fmt.Println("Len:", r.Len())
    	fmt.Println("Cap:", r.Cap())
    	fmt.Println(r.SlicePrev())
    	fmt.Println(r.SliceNext())
    
    	// Output:
    	// Len: 15
    	// Cap: 20
    	// [4 3 2 1 0]
    	// [5 6 7 8 9 10 11 12 13 14]
    }
    func ExampleRing_Link_SameRing() {
    	r := gring.New(10)
    	for i := 0; i < 5; i++ {
    		r.Set(i).Next()
    	}
    
    	same_r := r.Link(r.Prev())
    
    	fmt.Println("Len:", same_r.Len())
    	fmt.Println("Cap:", same_r.Cap())
    	fmt.Println(same_r.SlicePrev())
    	fmt.Println(same_r.SliceNext())
    
    	// Output:
    	// Len: 1
    	// Cap: 1
    	// [4]
    	// [4]
    }

Unlink

  • 说明:Unlinkr.next()开始,从ring中删除n % r.len()个元素。如果n % r.len() == 0,则ring保持不变。返回值为删除的subring
  • 格式:

    Set(value interface{}) *Ring
  • 示例:

    func ExampleRing_Unlink() {
    	r := gring.New(10)
    	for i := 0; i < 10; i++ {
    		r.Set(i).Next()
    	}
    
    	fmt.Println("Before Unlink, Len:", r.Len())
    	fmt.Println("Before Unlink, Cap:", r.Cap())
    	fmt.Println("Before Unlink, ", r.SlicePrev())
    	fmt.Println("Before Unlink, ", r.SliceNext())
    
    	r.Unlink(7)
    
    	fmt.Println("After Unlink, Len:", r.Len())
    	fmt.Println("After Unlink, Cap:", r.Cap())
    	fmt.Println("After Unlink, ", r.SlicePrev())
    	fmt.Println("After Unlink, ", r.SliceNext())
    
    	// Output:
    	// Before Unlink, Len: 10
    	// Before Unlink, Cap: 10
    	// Before Unlink,  [0 9 8 7 6 5 4 3 2 1]
    	// Before Unlink,  [0 1 2 3 4 5 6 7 8 9]
    	// After Unlink, Len: 7
    	// After Unlink, Cap: 7
    	// After Unlink,  [1 7 6 5 4 3 2]
    	// After Unlink,  [1 2 3 4 5 6 7]
    }

RLockIteratorNext

  • 说明:RLockIteratorNextRWMutex.RLock中迭代的回调给定的func f进行正向读取。如果fun f返回true,则继续迭代;如果返回false则停止。
  • 格式:

    RLockIteratorNext(f func(value interface{}) bool)
  • 示例:

    func ExampleRing_RLockIteratorNext() {
    	r := gring.New(10)
    	for i := 0; i < 10; i++ {
    		r.Set(i).Next()
    	}
    
    	r.RLockIteratorNext(func(value interface{}) bool {
    		if value.(int) < 5 {
    			fmt.Println("IteratorNext Success, Value:", value)
    			return true
    		}
    
    		return false
    	})
    
    	// Output:
    	// IteratorNext Success, Value: 0
    	// IteratorNext Success, Value: 1
    	// IteratorNext Success, Value: 2
    	// IteratorNext Success, Value: 3
    	// IteratorNext Success, Value: 4
    }

RLockIteratorPrev

  • 说明:RLockIteratorPrevRWMutex.RLock中迭代的回调给定的func f进行反向读取。如果fun f返回true,则继续迭代;如果返回false则停止。
  • 格式:

    RLockIteratorPrev(f func(value interface{}) bool)
  • 示例:

    func ExampleRing_RLockIteratorPrev() {
    	r := gring.New(10)
    	for i := 0; i < 10; i++ {
    		r.Set(i).Next()
    	}
    
    	// move r to pos 9
    	r.Prev()
    
    	r.RLockIteratorPrev(func(value interface{}) bool {
    		if value.(int) >= 5 {
    			fmt.Println("IteratorPrev Success, Value:", value)
    			return true
    		}
    
    		return false
    	})
    
    	// Output:
    	// IteratorPrev Success, Value: 9
    	// IteratorPrev Success, Value: 8
    	// IteratorPrev Success, Value: 7
    	// IteratorPrev Success, Value: 6
    	// IteratorPrev Success, Value: 5
    }

SliceNext

  • 说明:SliceNextslice的形式返回从当前位置向后所有元素的值的副本。
  • 格式:

    SliceNext() []interface{}
  • 示例:

    func ExampleRing_SliceNext() {
    	r := gring.New(10)
    	for i := 0; i < 10; i++ {
    		r.Set(i).Next()
    	}
    
    	fmt.Println(r.SliceNext())
    
    	// Output:
    	// [0 1 2 3 4 5 6 7 8 9]
    }

SlicePrev

  • 说明:SlicePrevslice的形式返回从当前位置向前所有元素的值的副本。 
  • 格式:

    SlicePrev() []interface{}
  • 示例:

    func ExampleRing_SlicePrev() {
    	r := gring.New(10)
    	for i := 0; i < 10; i++ {
    		r.Set(i).Next()
    	}
    
    	fmt.Println(r.SlicePrev())
    
    	// Output:
    	// [0 9 8 7 6 5 4 3 2 1]
    }
Content Menu

  • No labels

4 Comments

  1. fmt.Println("Cap:", r.Cap())
    本地运行Link()接口的例子,发现输出和预期不同,链接后的ring容量是19,预期是20,这个现象看着像bug。
    也就是:Link后的Cap的计算有错误
    1. 我把ExampleRing_Link_Common方法的代码拷贝出来跑了没有出现Cap=19的情况, 你可以贴一下你的代码么?

      1. 我也是把ExampleRing_Link_Common的代码拷贝出来运行的,出现了cap = 19。我看了Cap()的实现,gf版本:v1.16.6,认为问题出现在这里:

        // Checks and updates the len and cap of ring when ring is dirty.
        func (r *Ring) checkAndUpdateLenAndCap() {
        ....
        totalLen := 0
        emptyLen := 0
        if r.ring != nil {
        r.mu.RLock()
        for p := r.ring.Next(); p != r.ring; p = p.Next() {
        if p.Value == nil {
        emptyLen++
        }
        totalLen++
        }
        r.mu.RUnlock()
        }
        ......
        }

        totalLen初始值为0,for里面结束条件是 p = 环的第一个节点,而p的初始值是第二个节点,导致环中第一个节点没有算进长度里。您看看是不是这里的问题
        1. 这个代码是基于V2版本写的sample, V2版本的gring的checkAndUpdateLenAndCap的实现已经修改过了. 

          你可以拉一下master分支看一下V2版本的实现