- 投稿日:2020-10-21T22:55:25+09:00
Go Modules(vgo)について
Go Modulesとは
Goの依存関係管理ツールです。一昔前まではdepが多く使われていましたが、Go1.11から導入され、多く使われているそうです。
ちなみに、Go1.13から本格的に導入で、Go1.11~1.12は移行期ということなので該当している場合は、バージョンアップします。また、下記のコマンドで環境変数の確認をし、GO111MODULEをonにすることでも使えるようになるようです。
$ go env GO111MODULE="on" GOARCH="amd64" GOBIN="" . . . //下に続くGo Modulesの使い方
実際にプロジェクトを作るところから一連の流れに沿っていきます。まず、任意のディレクトリで任意のディレクトリで新規にプロジェクトを作成します。
また、Go Modulesを使う場合、GOPATH外でも置くことは出来ますが、保存先はGOPATH下になるそうです。→参考記事
※推奨は$GOPATH/src/github.com/username/任意プロジェクト(自分の場合: $GOPATH/src/github.com/username/testproject)
mkdir $GOPATH/src/github.com/username/testproject作成したプロジェクトに移動し
go mod init
を実行します。go mod init github.com/username/testprojecttestprojectと同じ階層に
go.mod
というファイルが生成されると思います。go.modmodule github.com/username/testproject go 1.** //各々のバージョンここにパッケージなどの
go get
によるインストールが記させていきます。試しにGoのフレームワークである、Ginをインストールしてみます。go get github.com/gin-gonic/gingo.modファイルに追記があるはずです。適宜、他ファイルでインポートして使用します。また、新しく
go.sum
というファイルも生成されます。ここに依存関係が記録されていきます。go.modmodule github.com/username/testproject go 1.** //各々のバージョン require github.com/gin-gonic/gin v1.6.3go.sumgithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= . . . //下に続くパッケージの削除
使用されていないパッケージは下記のコマンドで削除できます。また、そういった場合はエラーで教えてくれます。
go mod tidy github.com/gin-gonic/gin //例最後に
今回はGo Modulesについて最低限目ものして残しておきました〜。次はGoの基本型について何回かに分けて更新していこうと思います!ちょくちょく別の内容でもメモ残していくと思いますが!!
- 投稿日:2020-10-21T20:46:17+09:00
Go言語で簡単な画像処理のツールの類をつくってみた。
Go言語初学者です。普段の生息界隈はJS/TS+Javaですが、サーバーサイド言語の処理をもっと得意になりたいという理由から、今年からGo言語に挑戦しています。挑戦理由は「モダン, マルチスレッド, コンテナ関連での活躍」が挙げられます。
やはり、実際に何かを作って習得していくスタイルが自分には合っているので、今回は「画像処理」をテーマに、CLIとしてもAPIとしても使えるツールyellow-high5/pictarを作ってみました。画像処理といってもCNNを使って画像認識させるような高度なものではないです。
Go標準のimageパッケージ
まずはGo標準のimageパッケージがどんな仕組みになっているか簡単に確認してみました。
Point, Rectangle
座標点PointはintのXとYで構成されていて、長方形領域RectangleはPointのMinとMaxで構成されています。
Color
- Alpha...透明度
- CMYK...シアン、マゼンタ、イエロー、ブラック(Key Plate)で示した色の表現方法
- RGB...レッド、グリーン、ブルーで示した色の表現方法
- Gray..グレースケールはRGBだと3つの値全てが同じ値になります。
image.NRGBA
この構造体では画像を
Pix
でRed,Green,Blue,Alphaを繰り返す1次元配列として扱います。Stride
とは画像の横一列分のサイズを表しています。imagingライブラリを読んでみる
画像処理が専門領域ではない人間には、難しい計算式を理解できないのでライブラリを使用します。今回はdisintegration/imagingを利用します。ソース自体も簡潔にまとまっていて、とても読みやすいです。機能としては以下のようなことができます。
画像処理
- adjust(調整)...グレースケール、反転、コントラスト、サチュレーション
- convolution(畳み込み)...3x3圧縮、5x5圧縮
- effects...ぼかし、シャープ
- histogram(正規化されたヒストグラム)...256(16x16)の配列に明るさを表現する
- resize...サイズ変更、切り抜き、スケール変更(fit)、サムネイル化
- transform...反転(Flip)、転置(Transpose)、回転(Rotate)
補助ユーティリティ
- io...画像読み込み、画像を開く、画像書き込み、画像保存、画像の向き(EXIFフラグ)の読み取り、変換、修正
- scanner...長方形で指定された領域を読み込む
- tools...新規画像作成、コピー、ペースト、透過
- utils...parallel(並列処理)、その他ユーティリティ
番外編:画像処理の用語集
ツールを作るには、画像処理の用語をある程度理解しておく必要があると感じたので、知識を整理しておきます
- HSV色空間...色相(Hue)、彩度(Saturation)、明度(Value)の3つからなる成分空間。原色の加減法混合で決まるRGB空間より直感的でわかりやすいらしいです。
- HLS色空間...色相(Hue)、輝度(Lightness)、彩度(Saturation)の3つからなる成分空間。HSV空間と似ています。
- 彩度...高いと画像の色が濃くなり、低いと画像の色が薄くなるイメージ。
- コントラスト...高いと画像の明暗差がはっきりし、低いとぼんやりするイメージ。
- 明度...高いと白っぽくなり、低いと黒っぽくなるイメージ。
- ガンマ補正...素直な比例関係ではなく、人間の視覚特性に合わせたRGBの補正方法。
- ガウシアンぼかし...シグマ値がぼかす量にあたる。
- シグモイド関数...DeepLearningでは、「この画像に書かれている数字は1である確率」を算出するのにお馴染みの関数でしたが、画像処理ではコントラストを調整するのに使われているようです。
並行処理
disintegration/imagingでは、画像を処理する際に並行処理を利用しています。これにより比較的早い処理ができるようです。画像処理の速度について計測している方がいらっしゃったので、詳しく知りたい人はこちらを参考にすると良いかと思います。
OpenCV, GoCV, Go言語における画像処理のパフォーマンスの比較 - ZOZO Technologies TECH BLOG
では、このライブラリではgoroutineでどのような並行処理が施されているのでしょうか。ヒントは以下のparallel関数にありました。
imaging/utils.go// parallel processes the data in separate goroutines. func parallel(start, stop int, fn func(<-chan int)) { count := stop - start if count < 1 { return } procs := runtime.GOMAXPROCS(0) limit := int(atomic.LoadInt64(&maxProcs)) if procs > limit && limit > 0 { procs = limit } if procs > count { procs = count } c := make(chan int, count) for i := start; i < stop; i++ { c <- i } close(c) var wg sync.WaitGroup for i := 0; i < procs; i++ { wg.Add(1) go func() { defer wg.Done() fn(c) }() } wg.Wait() }countは、実行する必要のある処理の数です。画像処理の例だと画素数や画像横一列分などがこれにあたります。
procsは、同時実行させる処理の数です。(デフォルトはCPUの数になっています。limitで同時処理するgoroutineの数を指定した場合はlimitが採用されます。)チャネルにcount数の入力値を送信しておき、procs数のgoroutineがチャネルから入力値を受信し、渡された関数で並列的に処理させます。
以下にimaging.FlipH(画像の左右を反転させる処理)がどのような過程で並行処理して出力するのかを表した絵を描いてみました。上の絵を実現しているコードfunc FlipH(img image.Image) *image.NRGBA { src := newScanner(img) dstW := src.w dstH := src.h rowSize := dstW * 4 dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) // 画像の高さの数だけ並行処理の仕事をさせる parallel(0, dstH, func(ys <-chan int) { // 1行分の画素群を反転させる for dstY := range ys { // 反転時の場所に各画素を配置 i := dstY * dst.Stride srcY := dstY src.scan(0, srcY, src.w, srcY+1, dst.Pix[i:i+rowSize]) reverse(dst.Pix[i : i+rowSize]) } }) return dst }
cobraでCLIツール
これらのライブラリをラップしてCLIをcobraを使って作成していきます。
まずはCLIをデザインする場合はそのコマンドで実行するサブコマンドとオプションを洗い出しておきましょう。さらに、オプションはグローバルで適用できるようにするのかも考慮しておくと良いです。基本的にデザインパターンでいうところのビルダーパターンで作成しています。デザインの参考としてはcobraの実績でも取り扱われていますが、Hugoを模してみました。
Hugoではサブコマンドを定義するときは以下のように定義します。
「hoge」というサブコマンドを定義する場合package commands //構造体でオプションを定義している type hogeCmd struct { *baseBuilderCmd /*オプションを書き込んでいる*/ ... } // コマンドビルダーでオプションを返している func (b *commandsBuilder) newHogeCmd() *hogeCmd { // オプションの空インタフェースを定義 cc := &hogeCmd{} // cobraでコマンド定義 cmd := &cobra.Command{ Use: "hoge", Short: "Short Description", Long: `Long Description`, RunE: func(cmd *cobra.Command, args []string) error {...}, } // サブサブコマンドがあれば、定義 cmd.AddCommand(...) // オプションをフラグとして定義 cmd.Flags().StringVarp(...) // ビルダーを登録しておく cc.baseBuilderCmd = b.newBuilderBasicCmd(cmd) return cc }コマンドビルダーに必要なサブコマンドを追加していけば完成していきます。コマンドビルダーの設計についてはこのファイルを見るとよく理解できます。
Ginで画像処理サーバー
画像をhttpでPOSTすると、画像を加工してオブジェクトストレージ(今回はS3)に保存するという機能を作成しました。加工内容は設定ファイルから読み込む仕組みです。アプリでプロフィール画像の登録やサムネイル作成などに使える機能を想定して実装しました。
Ginのロジック
Go製のWebフレームワークであるGinのGoDocを読んで大雑把に絵にしました。かなり端折ってしまっていますが、簡略化するとこんな感じかと。処理をHandlerFunc(ミドルウェア)でつないで、HTTPリクエストからHTTPレスポンスを返すロジックを作成しているようです。
- Engine...フレームワークのインスタンス(
gin.Default()
あるいはgin.New()
で生成される)- Context...最も重要な部分。受け取ったリクエストからレスポンスを返すまでの情報を保持する。
- HandlerFunc...処理ロジック(Dファイル処理からロギングまで多様な処理を記述できる)
- HandlersChain...処理ロジックを集めた配列。一連の処理の流れを作るチェーン。
- RouterGroup...処理ロジックとURIのエンドポイントを繋ぐ
HTTP処理をミドルウェアチェーンで表現するあたりは、Node.jsのExpressとよく似てます。
S3へのファイルアップロード
脱線しましたが、本題のファイルアップロードの処理に話を戻します。処理の流れは大まかに3ステップ。
- HTTPリクエストボディで指定されたクライアントからの画像を読み込みサーバーのファイルシイステムへ保存。
- 読み込んだファイルをimagingライブラリで加工処理する。
- 加工処理を施した画像ファイルをS3へアップロードして、成功ステータスを返す。
Goへのファイルアップロードについては以下を参考にしました。詳細な設定を行う場合はAmazon Web Services - Go SDKを参考にしてください。
viperを使えば、オブジェクトストレージの接続設定や画像の保存名など詳細設定をの設定ファイル(config.jsonなど)に外出しすることも可能です。
まとめ
調べていくうちにGinの実績でも紹介されているGo製の画像処理サーバーが見つかりました。
こちらの方が私のような初心者なんちゃってツールより流石によく設計されています。サービス実装で作るときは遠慮なくこちらを使おうと思いました。自分で作ろうとしていたものの解が見つかると学習がより深まります。
とりあえずは、Goの標準パッケージや並行処理を使いこなせるようになるのが自分の課題だと感じました。Goのパッケージ類は見通しがよく、あまり疲れないのでしばらく鍛錬できそうです。
- 投稿日:2020-10-21T19:09:49+09:00
Golangのinterface型
- 投稿日:2020-10-21T13:52:55+09:00
【Go】WSL2にGoをインストールする手順
WSL2にGoをインストールする
いままでWindowsにインストールしたGoを使用してたけどどうせならWSL2で開発したいのでWSL2にGoをインストールしてみる
実行環境
OSはWindows 10 Pro 64bit (バージョン2004 OSビルド19041.572)
WSL2でOSはUbuntu-20.041.インストーラーをダウンロードする
まずはDownload and install - The Go Programming Language を開き「Linux」を選択し、Linux用のインストーラーをダウンロードしてくる。
この時にダウンロードしてきたインストーラー(例では
go1.15.3.linux-amd64.tar.gz
)を自分のわかりやすいところへ移動しておく2.WSLを立ち上げる
次にコマンドプロンプトかWindowsのターミナルを開き、
wsl
コマンドを実行してWSLを立ち上げるMicrosoft Windows [Version 10.0.19041.572] (c) 2020 Microsoft Corporation. All rights reserved. C:\Users\sola>wsl root@sola-pc:/mnt/c/Users/sola#3.公式サイトに記載されてるコマンドを実行する
無いとは思いますが予めGoがインストールされている場合はアンインストールしておいてくださいとのこと
まず以下のコマンドで
/usr/local
以下に展開
※先ほどダウンロードしてきたインストーラー(例ではgo1.15.3.linux-amd64.tar.gz
)を置いた場所へ移動してから実行することtar -C /usr/local -xzf go1.15.3.linux-amd64.tar.gz4.ルートへ移動後エクスプローラーを立ち上げる
終了後、ルートへ移動し、そこでエクスプローラーを立ち上げる
root@sola-pc:/mnt/c/Users/sola# cd ~ root@sola-pc:~# explorer.exe . root@sola-pc:~#
explorer.exe .
を実行すると以下のようなエクスプローラーが立ち上がる(※環境によってファイルなどに差異はあるとおもいますので、あくまでこんな感じのディレクトリが開かれるというイメージで見てください)
5.環境変数の設定
.bashrc
をテキストエディタで開き、以下の行を追加し保存する。export GOROOT=/usr/local/go export GOPATH=$HOME/go export PATH=$GOPATH/bin:$GOROOT/bin:$PATHその後、コマンドプロンプトorターミナルを再起動させて再度WSLを立ち上げる
6.Goがインストールされているか確認
wsl
コマンドで立ち上げたのち、go version
でインストールされているか確認しておくMicrosoft Windows [Version 10.0.19041.572] (c) 2020 Microsoft Corporation. All rights reserved. C:\Users\sola>wsl root@sola-pc:/mnt/c/Users/sola# go version go version go1.15.3 linux/amd64 root@sola-pc:/mnt/c/Users/sola#参考URL