helloworlds

not a noun, it's a verb

【Go】Golang プロジェクト構成を考える

golangを使って色々と試したいなと思い調べていると、 どうもプロジェクト構成についてよく考えたほうが良さそうだった。

その時のメモとこれから随時、理解をしていきながら編集&更新していけたらと思う。 なので、ご指摘(できれば優しいアドバイスooo〜)ありましたらよろしくお願い致します。

まずは、

GOPATH

GOPATHは任意のディレクトリを指定してもおk。 そして、PATHを通す。

export GOPATH=$HOME/go
export PATH=$GOPATH/bin:$PATH

こちらは公式brewでインストールした場合などに、 ファイルに書き込むことになるだろう。 ($ echo $GOPATHで、パスを確認。)

ただ、gvmという、バージョン管理ツールをインストールすると、 上記の設定はgvmがやってくれるらしいので、そちらでも良さそう。 (.bashrcに自動読み込み。即反映するには、$ source /home/ec2-user/.gvm/scripts/gvm実行。)

gvm

  • gvmをインストール

xcodeも必要になります。

$ brew install mercurial
$ bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
  • gvm確認
$ gvm version
Go Version Manager v1.0.22 installed at /<Path>/<To>/.gvm
  • gvm installできるgolangのヴァージョンを確認
$ gvm listall
  • gvm install
$ gvm install go1.9.2

-Bオプションでバイナリからインストール。

  • gvmでインストールした任意のヴァージョンを使う/切り替え
$ gvm use go1.9.2 --default

--defaulオプションで、terminalで再度ログインした後も指定したヴァージョンで使用できるようになる。

  • goコマンドでヴァージョン確認
$ go version
go version go1.9.2 linux/amd64
  • gvmでインストールしたヴァージョン一覧を表示
$ gvm list
gvm gos (installed)

   go1.8.4
   go1.9.2
   system
  • gvmをアンインストール
$ gvm implode

dep

依存関係管理(パッケージ管理)ツールです。 他のツールとしては、glideなどがありますが、goの公式開発チームがサポートしているツールみたいなのでdepを使用してみた。

depを使用するメリットとして、他のプログラマーと開発する際、外部パッケージのヴァージョン管理が容易になります。 また、depを使用することで、Gopkg.lockGopkg.tomlvendor/ができあがります。 こちらの出来あがるファイルやディレクトリについては、後ほど。

  • depをインストール
$ brew install dep
$ dep version
dep:
 version     : devel
 build date  :
 git hash    :
.
.
.

一旦ここまで。 次は、プロジェクト構成を確認してから、depコマンドを使ってみます。

プロジェクト構成

GOPATH配下にsrc、その配下にわかりやすいようにgithub.com/<ユーザー名>/としてディレクトリを構成してみた。 下の構成でいうとgotest, gotest2がプロジェクトになります。 ソースコードこちらの記事のものをサンプルプロジェクトとして使用させて頂きました。

$GOPATH
└── src
    └─ github.com
       │
       └── <UserName>
           ├── gotest
           └── gotest2

以下、gotestプロジェクトの構成

gotest/
|── Gopkg.lock
├── Gopkg.toml
├── Makefile
├── README.md
├── app
│   ├── app.yaml
│   └── main.go
├── gae
│   └── hello.go
└── vendor
    └── github.com
        ├── gorilla
        └── ryutah

ここで先ほどのdepで更新されるファイルがあるかと思います(Gopkg.lock、Gopkg.toml、vendor/)。 これらを作成していくので、プロジェクトディレクトリに移動して、以下を実行していく。 (glideからdepへの移行は、こちらの記事が非常に参考になりました!)

  • dep initを実行 Gopkg.lock、Gopkg.toml(編集可能)、vendor/を生成。
$ dep init

-vオプションで、ログを出力しながらinit。

  • depでパッケージを追加&追記

例えば、main.goで定義してあるパッケージでインストールされてなければインストールされる。

$ dep ensure
$ dep ensure -add <PACKAGES>
  • depでパッケージをアップデート
$ dep ensure -update <PACKAGES>
  • depパッケージの状態を確認
$ dep status

ローカルサーバーを立ち上げる

goapp serve -port <port num> app.yaml

エラーがでなければ完了です。

おわり

gvmとdepでシンプルにプロジェクトを管理できるのかなと思います。 また、ghq+pecoでさらに可動性アップできそうです。

トラブルシューティング

GOPATHがなんか変わってた〜


gvmを利用するとgoの環境変数が勝手に書き換わります。 なので、設定ファイルを編集する必要があります。

設定ファイル自体は、$HOME/.gvm/environments配下にありました。

  • 環境設定ファイルを作成
$ gvm pkgset create <name>

任意の名前を設定できる。私はわかりやすいように、go<version>@<project name>みたいにした。

  • 編集
$ gvm pkgenv <name>
  • 編集箇所

12行目と16行目。変更箇所のサンプルは以下。 プロジェクト名を追記していくかんじ。

# 12行目
export GOPATH; GOPATH="/Users/<mac user name>/.gvm/pkgsets/go1.9.2/gotest:$HOME/go:$GOPATH"

# 16行目
export PATH; PATH="/Users/<mac user name>/.gvm/pkgsets/go1.9.2/gotest/bin:${GVM_OVERLAY_PREFIX}/bin:$HOME/go/bin:${PATH}"
  • プロジェクト毎にpkgsetファイルを切替
$ gvm pkgset use <name>
  • pkgsetの一覧
$ gvm pkgset list

任意のプロジェクトディレクトリにて以下を実行。

$ gvm linkthis

【SQL】DBMS 内部アーキテクチャ

DBについて復習しようと思いました。なので、 「SQL 実践入門 (技術評論社)」という本を参考にメモがてら書きます。

SQL実践入門──高速でわかりやすいクエリの書き方 (WEB+DB PRESS plus)

SQL実践入門──高速でわかりやすいクエリの書き方 (WEB+DB PRESS plus)

今回は1章の内容です。

RDB(Relational Database)製品には、OracleMicrosoft SQL ServerDB2、PostreSQL、MySQLなどが存在する。 MySQLがよく日本では業務をする上で目にしたり、聞いたりするだろう。 内部のアーキテクチャはどれも同じというわけではない。しかし、RDBという枠組みでは基本は一緒、主な概要を抑えておけばよいだろう。

クエリ評価エンジン

ユーザから受け取ったSQLを解釈し、いかなる手順で記憶装置のデータへアクセスするべきか決定する。(実行プラン) この計画に基づいたデータへのアクセス方法がアクセスメソッド。

バッファマネージャ

メモリ領域の使い方を管理する。 ディスク容量マネージャと連携しながら動く。

ディスク容量マネージャ

どこに、どのようなデータを保存するかを管理する。 それに対する、読み込みと書き込みを制御する。

トランザクションマネージャとロックマネージャ

DBMS内部では、トランザクションという単位で個々の処理が管理される。 このトランザクション同士をデータの整合性を保ちながら実行させたり、データにロックをかけて待機させたりという機能です。

リカバリマネージャ

いざという時にデータの復旧(リカバリ)すること。

記憶装置

  • HDD

データを保存するストレージ。 ほとんどの場合は、容量、コスト、パフォーマンスなどという点からHDDあ選択されているでしょう。

  • メモリ

DBMSは常にディスク以外にもデータを持つようにしている。それがメモリです。 記憶コストが高く、1台のハードに搭載できる量は多くはない。 頻繁にアクセスされるデータをうまくメモリ上に保持しておくことができると、 SQL文を実行した際、パフォーマンスの向上が見込める。 パフォーマンス向上とする目的でメモリのことをバッファキャッシュと呼ぶ。

メモリ上の2つのバッファ

  • データキャッシュ

ディスクにあるデータの一部を保持するためのメモリ領域。

  • ログバッファ

更新処理(INSERT,DELETE,UPDATE,MERGE)の実行に関係する。 更新処理は、すぐにストレージ上のデータに変更をかけているわではなく、 更新情報をログバッファに一時溜めている。

トレードオフ

データキャッシュに比べてログバッファの設定値が非常に小さい。 これはDBが基本的に検索をメインとして想定しているからだ。 最近のDBMSは自動でメモリの割当をしているが、よりタスクが大規模化したり、細密化していけば どのような思想に基いてリソース配分が行われているか、行わなければならないのかは知っておく必要がありそうです。

ワーキングメモリ

ソートやハッシュなどの特定処理に利用される作業用の領域。 (ワークバッファやソートバッファなどと呼ばれる)

データへのアクセス方法はどのように決まるのか

さきほども出てきたクエリ評価エンジンでアクセスを決める。 流れとしては以下。(上から下へ)

SQL
|
parser
|
optimizer--> catalog manager
|
plan evaluation
  • パーサー

構文解析。 受け取ったSQLを要素毎に分解しDBMSが処理しやすいように変換する。

  • オプティマイザ パーサーからきたクエリをもとにデータアクセス方法を決定する。 インデックス有無やデータの分散や偏りの度合い、内部のパラメータなどの条件を考慮し計画を作成、 コストを計算して、最も低コストは1つに絞り込む。

  • 各テーブルのレコード数 2.各テーブルの列数と列のサイズ

  • 列値のカーディナリティ(値の個数)
  • 列値のヒストグラム
  • 列内にあるnullの数
  • インデックス情報

上記の情報をもとに実行計画を作成するわけだが、このカタログ情報が実際のテーブルやインデックスと一致しない場合。その場合は統計情報を更新する必要とある。(例:ANALYZE) 運用しているとANALYZEをするタイミングも重要ですが...w

  • カタログマネージャ

DBMS内の内部情報えお集めたテーブル群で、テーブルやインデックスの統計情報が格納される。(統計情報)

  • プラン評価

オプティマイザから受け取った実行計画で、最適な実行計画を選択する。

おわり

と、いった具合でDMNSのアーキテクチャをざくっとかいてみましたの巻。