0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

wfs - Go で書き込み可能な io/fs

Posted at

wfs とは

jarxorg/wfs で開発している Go標準 の io/fs を拡張したライブラリです。 現在は以下のファイルシステムをサポートしています。

  • osfs
  • memfs
  • s3fs
  • gcsfs

開発の動機

Go で S3 や GCS を使うほとんどのプロジェクトで、クラウドストレージにアクセスするためのインタフェースを新しく定義し、開発用にローカルファイルシステムの実装、テスト用にメモリ上での実装をして切り替えれるようなコードを書いてきました。

Go1.16 から登場した io/fs は今のところ読み取り専用で、書き込みについては proposal: io/fs: add writable interfaces などで議論されていますが簡単には進まなそうです。

その Issue でも紹介されている afero や billy は非常に優秀ですが S3 に対応していなかったりして微妙に私のユースケースにマッチしません。

そこで io/fs を拡張した wfs を開発することにしました。

書き込みサンプル

package main

import (
	"fmt"
	"io/fs"
	"log"
	"os"
	"strings"

	"github.com/jarxorg/gcsfs"
	"github.com/jarxorg/s3fs"
	"github.com/jarxorg/wfs"
	"github.com/jarxorg/wfs/memfs"
	"github.com/jarxorg/wfs/osfs"
)

func newFS(dir string) fs.FS {
	if strings.HasPrefix(dir, "s3://") {
		return s3fs.New(strings.TrimLeft(dir, "s3://"))
	}
	if strings.HasPrefix(dir, "gs://") {
		return gcsfs.New(strings.TrimLeft(dir, "s3://"))
	}
	if strings.HasPrefix(dir, "memfs://") {
		return memfs.New()
	}
	return osfs.New(dir)
}

func main() {
	dir := "memfs://dummy"
	if len(os.Args) > 1 {
		dir = os.Args[1]
	}

	name := "example.txt"
	content := []byte(`Hello`)

	fsys := newFS(dir)
	_, err := wfs.WriteFile(fsys, name, content, fs.ModePerm)
	if err != nil {
		log.Fatal(err)
	}

	wrote, err := wfs.ReadFile(fsys, name)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("wrote: %s/%s\n\n%s\n", dir, name, string(wrote))
}

CopyFS サンプル

書き込めるようになったので、便利な CopyFS 関数という副産物も生まれました。

package main

import (
	"log"

	"github.com/jarxorg/s3fs"
	"github.com/jarxorg/wfs"
	"github.com/jarxorg/wfs/osfs"
)

func main() {
	src := s3fs.New("your-bucket")
	dst := osfs.DirFS("local-dir")

	// NOTE: Copy files on s3://your-bucket to local-dir.
	if err := wfs.CopyFS(dst, src, "."); err != nil {
		log.Fatal(err)
	}
}

上記は s3 バケットからローカルにコピーするサンプルですが、以下も同じようなコードで簡単にできます。

  • gcs バケットから s3 にコピー
  • ローカルからメモリにコピー

※ 並列実行などしていないのであまり巨大なバケットのコピーにはご注意ください。

S3 や GCS の認証

S3 ならば s3fs.NewWithAPIs3fs.NewWithSession、GCS ならば gcsfs.NewWithClient を使うことができます。

最後に

いまのところ追加開発の予定はありませんが、バグなどあれば精力的になおしていくつもりです!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?