この記事の内容は以下のバージョンで作りました。
> go version
go version go1.13 windows/amd6
きっかけ
- ちょっとしたgoのコードを書いているときに、「リソースの開放が面倒だなぁ」とおもった。
- .NETだと、usingステートメントですごくすっきりかけるから、似たようなものを作りたい。
通常のgoの場合
// 何らかのリソースを取得するresource,err:=hogehoge.GetResource()// エラーがあるかどうか調べてちょめちょめするiferr!=nil{// ちょめちょめ}// 解放忘れがないように、deferを定義deferresource.Close()// ようやく本来やりたい処理みたいな感じになる。本来やりたい処理を書き始めるまでいつまでかかるんだ・・・
という感じ
今回作ったもの
typeIDisposeinterface{open()errordispose()}funcUsing(disposableIDispose,fnfunc(resourceinterface{})error)(errerror){iferr=disposable.open();err!=nil{returnerr}deferdisposable.dispose()iferr=fn(disposable);err!=nil{returnerr}returnnil}IDisposeな構造体と関数を受け取り、Open/実行/Closeまでを自動的にやってくれるやつ。
使い方
IDisposeな構造体を用意
typeDisposableStructstruct{hogeResouce*hoge.HogeResource}func(s*DisposableStruct)open()error{returnnil}func(s*DisposableStruct)dispose(){// リソースを破棄する処理s.hogeResouce.Close()}実行部
err:=Using(&DisposableStruct{hogeResouce:nil},func(rinterface{})error{// castする必要がある。イケてない部分1hoge:=r.(*DisposableStruct)// ここに本来やりたい処理を書く// 戻り値はエラーのみ。イケてない部分2returnnil})最後に
- ジェネリクスが使えれば、もっとかっこよくかけるんだけど・・・
- golangでこんな無駄なことしてんじゃねぇよみたいに言われるかもしれないけど、気にしない。
- もっといい感じの実装がある場合はコメント欄で指摘をお待ちしております!
- 実際にはステートメントではなくただの関数です(タイトル詐欺ですまんな)