LoginSignup
2
2

More than 1 year has passed since last update.

Goの io/fs.FS をOSのファイルシステムにマウントする

Last updated at Posted at 2022-08-27

fs.FS内のファイルを他のプロセスに渡したい

Go 1.16 で追加された io/fs パッケージで色々なファイルシステムに共通のインターフェイスでアクセスできて便利になりました.このfs.FSの中身にシェルやエクスプローラからアクセスして操作できると便利そうです.

例えば,ネットワークストレージのクライアントを Go で実装する場合 fs.FS インターフェイスを実装すると思いますが,そのクライアントをそのままマウントできれば他のアプリケーションからデータにアクセスできます.

GoでFUSEを使う

大抵の環境では,ユーザプログラムがファイルシステムを提供するためのFUSEという仕組みが使えます.

Linuxの場合は,go-fuse というbindingsがあります.

専用のインターフェイスを提供する必要があってfs.FSを使うのは少し面倒ですが,高機能かつ活発に開発が続いています.

Windowsの場合は,DokanというWindows上でFUSEのようなものを提供するライブラリがあって,dokan-goというbindingsもありました.

しかし,ずっとメンテナンスが止まっていて,最近の環境だとコンパイルするために少しだけ修正が必要です.

(8/28追記: DokanではなくWinFspのGoのbindingsは最近までメンテナンスされてそうでした.cgofuse )

dkango

以前から,go-fuse と dokan-go のラッパーを書いて使っていたのですが,dokan-goの本家のリポジトリはずっとメンテナンスが止まっていて,自分で修正しながら使うのも面倒になってきました.特にcgoを使っているので久しぶりに使おうとするとWindows上のgccのセットアップではまったりします.

仕方ないので,dkangoというライブラリを書きました.Goだけで実装したのでcgoは使わないです.

unsafeとsyscallの塊でそんなにテストもしてないので,クラッシュしたりするバグが残ってるかもしれません. 自分でしばらく使っていますが大丈夫そうでした.

fsmount

上記のdkangoとgo-fuseを環境に合わせて使い分けるラッパーです.

fs.FSとマウントポイントを渡すだけで簡単にマウントできます.Windows以外はあまりテストしていませんが,Windows/Linux/MacOSで似たような動作をすると思います.

package main

import (
	"os"
	"github.com/binzume/fsmount"
)

func main() {
	mount, _ := fsmount.MountFS("X:", os.DirFS("."), nil)
	defer mount.Close()

	// Block forever
	select {}
}

この例ではカレントディレクトリからFSを作って X: ドライブとして追加します.(Linuxの場合はマウントポイントとして適当なディレクトリを指定してください)

いくつかメソッドを実装すれば書き込み可能にもなりますが,そのあたりはサンプルを参照してください.

最後に

カジュアルにファイルシステムを実装できると色々遊べると思います.

非実用的なサンプルとしてリバーシの盤面をマウントしてみた例です.フォルダを開くごとにゲームが進みます.無駄にAIとも対戦できます.このファイルシステムはリバーシのすべての可能な状態を含んでいる上にパフォーマンスも良くないので,ディレクトリをすべてスキャンするようなソフトウェアは止めておいたほうが良さそうです.

2
2
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
2
2