Fundamentals 5 min read

Mastering Go’s container/ring: Build and Optimize Circular Linked Lists

This article explains Go's container/ring package, detailing its Ring type, core methods, performance characteristics, practical code examples, and typical use cases such as schedulers and resource pools for efficient circular data handling.

Ops Development & AI Practice
Ops Development & AI Practice
Ops Development & AI Practice
Mastering Go’s container/ring: Build and Optimize Circular Linked Lists

Introduction

The Go standard library includes the container/ring package, which implements a circular linked list—a data structure where the last element points back to the first, enabling seamless cyclic traversal useful for resource pools, round‑robin scheduling, and similar scenarios.

Basic Structure

The package defines a Ring type:

type Ring struct {
    next, prev *Ring
    Value interface{} // stored data
}

Each Ring node holds pointers to the next and previous nodes; a single‑element ring points to itself.

Main Functions and Methods

New(n int) *Ring

– creates a ring with n elements. Next() *Ring – returns the next node. Prev() *Ring – returns the previous node. Move(n int) *Ring – moves forward or backward n positions. Link(s *Ring) *Ring – inserts another ring after the current node. Unlink(n int) *Ring – removes a sub‑ring of n nodes starting from the current node. Do(f func(interface{})) – applies a function to every element in the ring.

Usage Example

The following program demonstrates creating, initializing, printing, and linking rings:

package main

import (
    "container/ring"
    "fmt"
)

func main() {
    // Create a ring with 3 elements
    r := ring.New(3)
    // Initialize values
    n := r.Len()
    for i := 0; i < n; i++ {
        r.Value = i
        r = r.Next()
    }
    // Print original ring
    r.Do(func(p interface{}) { fmt.Println(p) })

    // Create another ring with 2 elements
    s := ring.New(2)
    s.Value = 10
    s = s.Next()
    s.Value = 20
    s.Do(func(p interface{}) { fmt.Println(p) })

    // Link the second ring after the first
    r.Link(s)

    // Print the combined ring
    r.Do(func(p interface{}) { fmt.Println(p) })
}

Running this code prints the values of the original ring, the second ring, and then the combined ring after linking.

Performance Analysis

Operations on a circular linked list are O(1) because they involve only pointer updates. However, random access is slower than array or slice indexing, as it requires traversal from the start of the ring.

Typical Application Scenarios

Circular linked lists excel in contexts that need periodic or cyclic access, such as round‑robin schedulers, resource‑pool management, and buffered channels where elements are frequently inserted and removed.

Conclusion

The container/ring package provides a robust implementation of circular linked lists, enabling developers to manage cyclic data efficiently, improve performance in suitable workloads, and simplify resource‑rotation logic.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

GoData Structuresexamplecircular linked listcontainer/ring
Ops Development & AI Practice
Written by

Ops Development & AI Practice

DevSecOps engineer sharing experiences and insights on AI, Web3, and Claude code development. Aims to help solve technical challenges, improve development efficiency, and grow through community interaction. Feel free to comment and discuss.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.