GoにいればGoに従え(29) container/ringをTinyGoで使ってみる

Joseph Halfmoon

前々回heap前回listとGoの標準ライブラリのcontainerを練習。今回はcontainerの最後の一つ ring です。しかし似たお名前のRingBufferがTinyGoのMachineパッケージの中に存在。今回は2つを比較してから、標準ライブラリのringの方をmicro:bit上で練習してみます。

※「GoにいればGoに従え」Go関連記事の総Index

go標準ライブラリのringとTinyGoのRingBuffer

ringもRingBufferもリングの形のデータ保持構造ではあるのですが、その適用は大分異なるものです。まず go の standard library のringについてのドキュメントは以下にあります。

ring

一方 TinyGo の machineパッケージの中の RingBuffer についてのドキュメントは以下です。

RingBuffer

Go素人が、勝手にほんわかしたところをまとめると以下の表のようになるのではないかと。知らんけど。

container/ring Machine package RingBuffer
データ型 Any byte
データ書き込み .Valueへ代入 Put()
フル時書き込み動作 上書き フルでは書き込み不可
データ読み出し .Value読み出し Get()
空読み動作 nilが返る エンプティでは読み出し不可
リングアクセス 双方向 単方向

TinyGoのRingBufferのお方は、いかにもUARTなどで通信したときの値などを一時バッファリングするための構造に見えます。「不可」と書かれているところは2番目の戻り値にfalseが返ります。それに対して標準ライブラリのringは、前回のlist構造の拡張的なものです。先へ先へと進んでいくと先頭に戻ってしまう、前へ前へと戻っていくと末尾へ戻ってしまう双方向のリストです。

これだけ性格が違うのでお名前は似ていても使い分けは大丈夫だあ。ホントか?

今回実験のTinyGoソースコード

今回のソースも御本家Go様の例題ソースをチョイ変です。殊更に Any な型のデータが突っ込めるぜという点、書き込んでないところを読み出すと<nil>だけれども、という点を「強調」してみました。

package main

import (
    "container/ring"
    "fmt"
)

func main() {
    rB := ring.New(3)
    nB := rB.Len()
    fmt.Println("Ring Len=", nB)
    rB.Value = 1
    rB = rB.Next()
    rB.Value = "abc"
    rB = rB.Next()
    for elem := 0; elem < nB; elem++ {
        fmt.Println(elem, " : ", rB.Value)
        rB = rB.Next()
    }
}
実験結果

上記のソースをビルドしてUSB接続したターゲット機BBC micro:bit v2 に書き込むコマンドラインは以下です。

$ tinygo flash --target microbit-v2

シリアルモニタで観察した動作は以下です。

mb20ringResult

最初の要素は未初期化なので <nil>、次は先頭に戻って整数で1、その次は文字列で abc と。ring してますなあ。

RingBufferの方も練習しておかないと。また次回か。

GoにいればGoに従え(28) container/listをTinyGoで使ってみる へ戻る

GoにいればGoに従え(30) math/bitsをTinyGoで使ってみる へ進む