いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

Goメモ-170 (循環リスト)(container/ring, 直近N件分だけ保持していたい)

概要

Goの標準パッケージの中に container というパッケージがあって、その中に少ないですがいくつか汎用のコンテナとして利用できる型があります。

んで、container/ring には、循環リスト があります。リングバッファとも言ったりしますかね。

イメージとしては、中華料理の回るテーブルみたいな感じです。要素の列に先頭と末尾の概念がなくて、円環状になるように接続されているもののイメージ。

要は、くるくると要素が入れ替わりながら配置されるバッファです。

ja.wikipedia.org

言語でリングバッファが標準ライブラリで用意されているのは珍しいですねー。

んで、このリングバッファさん、直近N件分だけを保持していたいときに結構便利な構造です。

配列とかスライスを使っていても普通に出来るのですが、いちいち処理書くのが面倒くさい。。ってときに使えたりします。

サンプル

package containers

import (
    "container/ring"

    "github.com/devlights/gomy/output"
)

// RingBuffer -- container/ring のサンプルです。(リングバッファ、循環リスト)
//
// REFERENCES
//   - https://pkg.go.dev/container/ring@go1.17.6
func RingBuffer() error {
    // container/ring は、循環リストを実装したものとなっている.
    // リング上のバッファをイメージすると分かりやすく、要素を追加していくと
    // 内容が入れ替わっていく。
    // 性質上、「直近N件分のみ保持しておきたい」場合などに便利。

    var (
        r  = ring.New(3)
        f1 = func(v interface{}) {
            output.Stdoutl("ring [next]", v)
        }
        f2 = func(v interface{}) {
            output.Stdoutl("ring [prev]", v)
        }
    )

    r.Do(f1)
    output.StdoutHr()

    for i := 0; i < 5; i++ {
        // 現在の番目に値を設定し、次の番目に進めて、それを保持しておく
        r.Value = i
        r = r.Next()

        r.Do(f1)
        output.StdoutHr()
    }

    // 循環しているのかどうかを確認
    for i := 0; i < 5; i++ {
        r = r.Prev()
        r.Do(f2)
        output.StdoutHr()
    }

    output.Stdoutl("ring-len", r.Len())

    return nil
}

実行すると以下のようになります。

gitpod /workspace/try-golang $ make run
go run github.com/devlights/try-golang/cmd/trygolang -onetime -example ""

ENTER EXAMPLE NAME: containers_ring

[Name] "containers_ring"
ring [next]          <nil>
ring [next]          <nil>
ring [next]          <nil>
-------------------------------------------------- 
ring [next]          <nil>
ring [next]          <nil>
ring [next]          0
-------------------------------------------------- 
ring [next]          <nil>
ring [next]          0
ring [next]          1
-------------------------------------------------- 
ring [next]          0
ring [next]          1
ring [next]          2
-------------------------------------------------- 
ring [next]          1
ring [next]          2
ring [next]          3
-------------------------------------------------- 
ring [next]          2
ring [next]          3
ring [next]          4
-------------------------------------------------- 
ring [prev]          3
ring [prev]          4
ring [prev]          2
-------------------------------------------------- 
ring [prev]          4
ring [prev]          2
ring [prev]          3
-------------------------------------------------- 
ring [prev]          2
ring [prev]          3
ring [prev]          4
-------------------------------------------------- 
ring [prev]          3
ring [prev]          4
ring [prev]          2
-------------------------------------------------- 
ring [prev]          4
ring [prev]          2
ring [prev]          3
-------------------------------------------------- 
ring-len             3


[Elapsed] 159.397µs

くるくる回っていることが確認できますね。


過去の記事については、以下のページからご参照下さい。

  • いろいろ備忘録日記まとめ

devlights.github.io

サンプルコードは、以下の場所で公開しています。

  • いろいろ備忘録日記サンプルソース置き場

github.com

github.com

github.com