[golang]goroutineの使い所3~画像ファイルを操作しよう!~

こんにちは。KOUKIです。とある企業でGo言語を使ったWebシステムの開発業務に従事しています。

ここ最近、goroutineの使い所について紹介してきました。

今回は、第3回目ということで、画像ファイルをサブネイル画像に変換するプログラムを紹介したいと思います。

画像ファイル(image/jpeg)

サブネイル画像

ちなみに、Udemyの「Learn the Why’s and How’s of concurrency in Go.」で学習したものを私の解釈付きで記載しています!※オススメです

ワークスペースの準備

実装

最初は、goroutineを使わないパターンを実装し、最後にgoroutineで並行処理化します。画像を扱うプログラムはちょっと頭を使うので、ハンズオンで少しずつ説明したいと思います^^

KOUKI
KOUKI

決して皆様の頭が悪いからと言いたいわけではなく、あくまで私が説明しやすいからです!

ルートパスを受け取る

最初に、以下のようにルートパスを受け取るプログラムを実装します。

パスを受け取るには、osパッケージのArgsメソッドを使用します。

以下のように実行します。

ルートパスから画像ファイルパスを取得する

取得したルートパス内を走破して、イメージパスを取得したいです。

そのためには、filepath.Walkを使用します。このメソッドは、引数に渡したルートパスを走破し、中に格納されているイメージファイルのパスを取得することができます。

ちなみに筆者は1~40.jpgファイルをimgs内に保存しています。

Todoコメントの箇所は、後ほど実装します。

このプログラムを実行してみましょう。

OKですね。

ファイルタイプを取得

ファイルタイプを取得する関数を作成しましょう。

私も初めて知ったのですが、ファイルパスからファイル情報を取得すると最初の512byteにファイルタイプが入るらしいです。

そして、この情報をhttp.DetectContentTypeに渡すとファイルタイプが取得できます。

実際にプログラムを実行してみましょう。

OKですね。注意点としては、「image/jpegファイルタイプのファイルしかこのプログラムは処理しません

サブネイル画像に変換

続いて、画像情報をサブネイルに変換する関数を実装をします。画像変換には、3rdパーティのdisintegration/imagingを使います。

サブネイル画像を保存

最後にサブネイル画像を保存します。

サブネイルデータを「thumbnail」ディレクトリ直下に保存するプログラムを実装しました。

プログラムを実行してみましょう。

OKですね。現状は完了までに6.530700563sの時間を要しますが、goroutineを使って時間を短縮してみましょう。

並行処理

さて、いよいよgoroutineを使って、並行処理を実装していきたいと思います。

今回は、walkfile(ディレクトリ走破) / processImage(画像の変換) / saveImage(画像の保存)のように工程が明確に別れている処理なので、goroutineの実装パターンの一つであるパイプライン処理が有効そうです。

パイプライン処理については、以前記事にしていますので、よかったら参考にしてください。

上記のイメージの通り、パイプラインの最初のステージは、walkFilesになります。

そのため、パイプラインをセットする関数を作成し、そこからwalkFilesを呼び出しましょう。

done Channelは、goroutineの処理パターンの一つで、パイプライン処理に置いて処理完了を示すシグナルを送るために使用します。

walkFiles関数には、新たにdoneチャネルを引数に渡し、戻り値としてイメージ画像パスとエラーのChannelを指定しました。

次は、processImageのパイプライン化です。

result Structには画像ファイルの処理結果を格納しています。

また、最初のパイプラインで画像のパスをpathsチャネルで取得しますが、これはgoroutineで動かしているので、channelには画像ファイルパスが逐次送られてくるようになっているため、5回ほどループを回し、pathを処理しています。

最後は、画像保存処理の呼び出しをパイプライン化します。

非常に長くなりましたが、これで完成です。

プログラムを実行して見ましょう。

結果は、「計測時間: 3.043700349s」でした。結構早くなりましたね!

おわりに

goroutineに加えてパイプラインの概念が入ってくると少し難しく感じます。

並行処理前のコードを何度か並列化することで、徐々に慣れていくことをオススメします!

それでは、また!

Go記事まとめ

関連図書

実装コード