いろいろ備忘録日記

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

Goメモ-642 (io.OffsetWriterを使って複数の区画に並行して書き込み)

関連記事

GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ

概要

以下、自分用のメモです。

たまにしか利用しませんが、io.OffsetWriter を使って一つのファイルの複数の区画に対して並行して書き込むようなことをしたりします。固定長なレコード構成しているファイルの場合ですね。オフセットによって、書き込むデータの位置が決まっている場合は有効なTipsです。

サンプル

multi_offsetwrite.go

package ioop

import (
    "encoding/hex"
    "errors"
    "io"
    "os"
    "sync"
)

// MultiOffsetWrite は、io.OffsetWriter を非同期で複数実行し、それぞれ異なるオフセット位置に書き込むサンプルです.
//
// REFERENCES:
//   - https://pkg.go.dev/io@go1.25.4#OffsetWriter
func MultiOffsetWrite() error {
    var (
        file *os.File
        err  error
    )
    file, err = os.CreateTemp(os.TempDir(), "trygolang")
    if err != nil {
        return err
    }
    defer os.Remove(file.Name())
    defer file.Close()

    //
    // ファイル内は指定バイト数ごとに区画が決まっているとする
    // 各区画は独立しており、それぞれデータ列を持つとする
    // 以下は、各区画ごとに *io.OffsetWriter を割り当てて一気に書き込んでいる
    //
    const (
        NUM_REGIONS = 10 // 区画の数
    )
    var (
        errCh = make(chan error, NUM_REGIONS)
        wg    sync.WaitGroup
    )
    for i := range NUM_REGIONS {
        var (
            ow = io.NewOffsetWriter(file, int64(i*20))
        )
        wg.Go(func() {
            var (
                buf = []byte("1234567890")
            )
            if _, err := ow.Write(buf); err != nil {
                errCh <- err
            }
        })
    }

    wg.Wait()
    close(errCh)

    var (
        sErrs = make([]error, 0)
    )
    for err := range errCh {
        if err != nil {
            sErrs = append(sErrs, err)
        }
    }
    if len(sErrs) > 0 {
        return errors.Join(sErrs...)
    }

    //
    // 読み直し
    //
    var (
        data   []byte
        dumper = hex.Dumper(os.Stdout)
    )
    defer dumper.Close()

    if data, err = os.ReadFile(file.Name()); err != nil {
        return err
    }

    dumper.Write(data)

    return nil
}

実行

$ task
task: [build] go build -o "/home/dev/dev/github/try-golang/try-golang" .
task: [run] ./try-golang -onetime

ENTER EXAMPLE NAME: ioop_offset_write_multi

[Name] "ioop_offset_write_multi"
00000000  31 32 33 34 35 36 37 38  39 30 00 00 00 00 00 00  |1234567890......|
00000010  00 00 00 00 31 32 33 34  35 36 37 38 39 30 00 00  |....1234567890..|
00000020  00 00 00 00 00 00 00 00  31 32 33 34 35 36 37 38  |........12345678|
00000030  39 30 00 00 00 00 00 00  00 00 00 00 31 32 33 34  |90..........1234|
00000040  35 36 37 38 39 30 00 00  00 00 00 00 00 00 00 00  |567890..........|
00000050  31 32 33 34 35 36 37 38  39 30 00 00 00 00 00 00  |1234567890......|
00000060  00 00 00 00 31 32 33 34  35 36 37 38 39 30 00 00  |....1234567890..|
00000070  00 00 00 00 00 00 00 00  31 32 33 34 35 36 37 38  |........12345678|
00000080  39 30 00 00 00 00 00 00  00 00 00 00 31 32 33 34  |90..........1234|
00000090  35 36 37 38 39 30 00 00  00 00 00 00 00 00 00 00  |567890..........|
000000a0  31 32 33 34 35 36 37 38  39 30 00 00 00 00 00 00  |1234567890......|
000000b0  00 00 00 00 31 32 33 34  35 36 37 38 39 30        |....1234567890|


[Elapsed] 602.921µs

参考情報

個人的Goのおすすめ書籍

個人的に読んでとても勉強になった書籍さんたちです。


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

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