AnyenvでGoのバージョン管理
概要
Anyenvとはこれ一つで色々なパッケージ管理ができるスグレモノのようです。今回はGolangまわりだけ整理していたので、Golangのセットアップ手順について書きます。
インストール
まずはリポジトリをクローン。
$ git clone https://github.com/riywo/anyenv ~/.anyenv
.zshrc
に以下を追記。
# anyenv export PATH="$HOME/.anyenv/bin:$PATH" eval "$(anyenv init -)"
goenv
をインストールします。
$ anyenv install goenv
$ goenv install 1.8
.zshrc
にGOPATHを設定します。(goenv rehashで解決してくれると思ったらそうでもない)
# Go export GO_VERSION=1.8 export GOROOT=$HOME/.anyenv/envs/goenv/versions/$GO_VERSION export GOPATH=$HOME/dev export PATH=$HOME/.anyenv/envs/goenv/shims/bin:$PATH export PATH=$GOROOT/bin:$PATH export PATH=$GOPATH/bin:$PATH echo Now using golang v$GO_VERSION
なんとなくnvm
と同じechoを追加します。
Now using node v6.10.1 (npm v3.10.10) Now using golang v1.8 $ go version go version go1.8 darwin/amd64
良い感じになりました。
まとめ
Version Managerにこだわりが無いようでしたら、新しい言語をインストールするときにあちこちVersion Managerを探しに行くよりサクッとインストールできるのでいいかなぁと思います。
リンク
Dockerのお掃除
概要
MBPの容量が圧迫しておりどうやら犯人はDocker for Macのようなのでお掃除していきます。
不要なコンテナの削除
Docker – Clean Up After Yourself! | Yohan Liyanage
こちらのブログより。
exited containersは自動削除されないとのことで、こちらを実行してくださいとの。
$ docker rm -v $(docker ps -a -q -f status=exited)
rmコマンドは少なくとも1つ以上の引数を必要とするので、
"docker rm" requires at least 1 argument(s). See 'docker rm --help'. Usage: docker rm [OPTIONS] CONTAINER [CONTAINER...] Remove one or more containers
このエラーが出た場合は削除できるexited containersが存在しないとのことなので気にせず進みます。
不要なイメージの削除
macos - How to clean up Docker for Mac containers - Ask Different
続いてこちら。 ポイポイしていきます。
$ docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v /etc:/etc spotify/docker-gc
不要なコンテナ・イメージの削除【追記】
Christinaさんよりアドバイスいただき、以下のコマンドで上記2つは解決できるそうです、ありがとうございます。
$ docker system prune
Docker.qcow2の削除
最後のこちらが一番大物で、私の場合は30GBほど占領していました。 キャッシュのようですが容量をこんなに占拠されては困りますのでポイポイしていきます。
$ rm ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/Docker.qcow2
ソース
Node.jsで内部変数・関数の取得
概要
テストやちょっとしたツールを作りたいときに内部変数・関数にアクセスしたい時がありますが、
そんなときに便利なのがvm
モジュールです。しかしvm
ではvar
の変数は取得できるものの、let
やconst
の変数は取得できません。
そこで色々試行錯誤して作ったツールについて書きます。
vmを用いた内部関数の取得
vm.runInNewContext
ではコードを実行時にglobalオブジェクトをセットすることができます。vm.runInThisContext
は自動的に現在のglobalオブジェクトが使われます。
この関数は実行時にglobalスコープ上のvar
をglobalオブジェクトに代入することで外からのアクセスを可能にしてくれますが、let
やconst
は変換されません。
sample.js
const test1 = 'test1'; let test2 = 'test2'; var test3 = 'test3'; function test(arg1, arg2, arg3) { const sum = arg1 + arg2 + arg3; let num1 = 1; var num2 = 2; num3 = 3; return sum + num1 + num2 + num3; }
exec.js
const vm = require('vm'); const fs = require('fs'); const path = require('path'); const filepath = path.resolve(__dirname, 'sample.js'); const file = fs.readFileSync(filepath, 'utf8'); const context = {}; vm.runInNewContext(file, context); console.log(context); /* * { test3: 'test3', * test: [Function: test] } // let, constが取得できない */
vm-agent
今回作ったツールはlet
, const
が取得できるのと、関数を自動実行して値を取得できるツールを作りました。
また関数の実行も可能です。
const fs = require('fs'); const path = require('path'); const { Agent } = require('vm-agent'); const filepath = path.resolve(__dirname, ''sample.js'); const file = fs.readFileSync(filepath, 'utf8'); const result1 = new Agent(file) .run() .getInnerVariable(); console.log(result1); /* * { test1: 'test1', * test2: 'test2', * test3: 'test3', * test: [Function: test] } */ const result2 = new Agent(result1.test) .setArguments(4, 5, 6) .run() .getInnerVariable(); console.log(result2); /* * { arg1: 4, * arg2: 5, * arg3: 6, * sum: 15, * num1: 1, * num2: 2, * num3: 3 } */
vm-agent/example at master · suguru03/vm-agent · GitHub
実装内容
実装内容はesprima
を用いてlet
, const
をvar
に変換し、escodegen
を用いてコードを再構築し実行するというものです。const
が上書きできてしまったりパフォーマンスが低下したりしますが、テスト用なのでいったん良しとします。
また関数の実行については、関数の引数を解析し変数に変換することでvm
モジュールでのアクセスを可能にしています。
ソース
Objective-CにおけるDate型の扱い
概要
なぜか最近仕事でObjective-Cを書いています。 サーバからmsのtimestampを受け取っているにも関わらず、時系列順に表示されなかったので調べてみました。
Types in Objective-C
まずはじめにハマったのが、msはint型には収まりません。JavaScriptの住人なのでここで時間をロスしました。
Types in objective-c on iPhone - Stack Overflow
この記事によると32bit端末ではlong型が4bytes扱い、64bit端末ではlong型が8bytes扱いだそうです。
Device一覧: https://en.wikipedia.org/wiki/List_of_iOS_devices
WikipediaによるとiPhone5S以降は64bitなので、long型を使うことにしました。(良いのかは不明)
Primitive sizes: The size of a char is: 1. The size of short is: 2. The size of int is: 4. The size of long is: 8. The size of long long is: 8. The size of a unsigned char is: 1. The size of unsigned short is: 2. The size of unsigned int is: 4. The size of unsigned long is: 8. The size of unsigned long long is: 8. The size of a float is: 4. The size of a double is 8. Ranges: CHAR_MIN: -128 CHAR_MAX: 127 SHRT_MIN: -32768 SHRT_MAX: 32767 INT_MIN: -2147483648 INT_MAX: 2147483647 LONG_MIN: -9223372036854775808 LONG_MAX: 9223372036854775807 ULONG_MAX: 18446744073709551615 LLONG_MIN: -9223372036854775808 LLONG_MAX: 9223372036854775807 ULLONG_MAX: 18446744073709551615
Dateの扱い
Objective-CではDateがmsをサポートしていないため、以下のように書かなければなりません。
NSNumber *timestamp = responseDict[@"timestamp"]; long ts = [timestamp doubleValue]; // coredataへ保存 NSDate *date = [NSDate dateWithTimeIntervalSince1970:ts/1000]; // ms -> s
JavaScriptの住人にとっては何だこれっていうレベルです。Swift知りませんが、きっとここらへんは改善されてるはず…祈
このプロジェクトではCoreDataにDate
型で保存していたため、secondまでしかサポートされておらず時系列順にソートすると残念な結果になったので、しれっとInteger 64
型に書き換えて保存するようにしました。
まとめ
せっかくならSwift書きたいです。
ソース
Google Cloud Platform上にContainer Clusterを作成する
概要
Google Cloud PlatformのContainer Cluster(Kubernetes)のセットアップからデプロイまでの手順です。プロジェクトの作成手順は省略します。
Container Clusterの作成
メニューから [Container Engine] -> [Container Clusters] を開き、[CREATE CLUSTER]をクリック。必要な項目を有効にして作成してください。 このプロジェクトではCloud SQLを利用しているので、Cloud SQLをEnabledにしています。
作成後、画面にConnectと出てくるので、メニューに従って実行します。
$ gcloud container clusters get-credentials production \ --zone {指定したzone} --project {project-id} $ kubectl proxy
gcloudのSDKはこちらからダウンロード可能です。
Cloud SDK | Google Cloud Platform
installの際にインストール不足のものはエラーとして表示されるので、それに従ってinstallして再度上のコマンドを実行すれば完了です。
http://localhost:8001/ui/にアクセスしKubernetesの画面が見れれば準備は完了です。
Redisのデプロイ
プロジェクトでredisを使用しているためredisのDockerイメージをデプロイします。Dockerをinstallしていない方はこちらからインストールできます。
$ docker pull redis:alpine $ docker tag redis:alpine gcr.io/{project-id}/redis:alpine $ gcloud docker push gcr.io/{project-id}/redis:alpine
これでRedisのデプロイは完了です。
コンテナの配置
後は先程のブラウザ上でコンテナを配置するだけです。
右上の[CREATE]をクリックし、必要に応じて入力してください。コンテナイメージのパスは [Compute Engine] -> [VM instances] のところのInstance templeteをコピペすれば完了です。 ポッド数は必要に応じて増やしてください。また今回のRedisは外部アクセスを許可していないので内部アクセスのみにしてあります。
他にNode.jsのDocker Imageもデプロイしましたがまた別の機会に作成手順と一緒に書きたいと思います。
感想
Docker & Kubernetes初日でしたが、同僚の手助けの下、数時間でNode.js/Redis Clusterの動作確認ができました。とても便利なので今後も使っていきたいです。
ソース
Pokemon Goのちょっと得する情報
カナダで一足先にプレイしています。ポケモン効果はすごいです、家から基本出なかったカナディアンの友達が毎日外出してます。
さて色々損してきたのでさくっと箇条書きでまとめときます。
- ピカチュウをゲットする
- 最初の三匹を選ばずに待っていると現れます。
- サークルは小さいほうが捕まえやすい
- サークル内にヒットすると捕まりやすくなるのと経験値がもらえる
- 足あとは少ないほど近い
- Lv30までは「ほしのすな」・「アメ」は使わない
- 卵のレベル上限はLv20
- 卵の内訳
- 有料ボックスは5km以上の卵に使ったほうがコスパいい
- 2kmは無限ボックスで孵化させましょう。
- Lv上限は現在40
- イーブイの進化のさせ方 (アニメ参照)
- リネームする (最初は大文字だよ、日本語対応してるかわからない)
- Sparkyが欲しい場合Jolteon
- Vaporeonが欲しい場合Rainer
- Flareonが欲しい場合Pyro
- 再起動する
- 進化させる
- リネームする (最初は大文字だよ、日本語対応してるかわからない)
- ズバット
- 玉の浪費なので高CPは逃げる
- カーブが気持ち射程長い気がしないでもない
- カーブはボールをくるくるすれば投げられる
- ラズベリーはポケモンが逃げにくくなる
- レアポケモンに使いましょう
- ボールを投げるごとにあげましょう
- ボールを投げた後にフリーズする
- いくら待っても結果は変わりません、再起動してください。
- googleアカウントをカナダにしてカナダドルでクレカ切るとお得
- 14,500コインでおそらく1,200円くらいお得ですかね(81円換算)
- Lure moduleのピンクのところをクリックするとアイテム使ってくれてる人がわかる
- 見てあげてください
- 個体値 *追記 6/23
- サイズがでかいほうが高い
- 進化はギリギリまでさせてはいけない
- ポッポマラソン *追記 6/23
- ポッポの入手が簡単
- 進化させると経験値が入る
- しあわせタマゴで経験値2倍
- ミューツー、ファイヤー、サンダー、フリーザーは伝説
- ミュウは(ry
Have a good Pokemon life!
リンク
- Master Balls, levelcap en zeldzame Pokémon gevonden in Pokémon GO broncode | Power Unlimited
- Pokemon GO Guide: How To Control Eevee’s Evolution - Page 2
- How to collect and hatch eggs in incubators to get the best rare Pokémon in Pokémon Go | WIRED UK
- https://twitter.com/PokemonGo_Hints/status/756827691714695168
- https://twitter.com/PokemonGo_Hints/status/756827955267969024
GAEからCloud Storageに画像をアップロードする
はじめに
Google App Engine (GAE)のGolangのAPI仕様がガラッと変わったようなので、古いバージョンを使っている方はここを参考に書き換えてください。
GitHub - golang/appengine: Go App Engine packages
Goのversionは1.6.2を使用しています。
画像のアップロード
実際はリクエストを受け取り、その画像をCloud Storageにアップロードしていますが、 実行しやすいようにローカルファイルとテストを使用しています。
package storage import ( "fmt" "google.golang.org/appengine" "google.golang.org/appengine/aetest" "google.golang.org/appengine/blobstore" "google.golang.org/appengine/image" "google.golang.org/appengine/log" "google.golang.org/cloud/storage" "io" "net/http" "os" "testing" ) const ( bucket = "<bucket path>" image = "<image path>" ) func Upload(req *http.Request) (string, error) { ctx := appengine.NewContext(req) client, err := storage.NewClient(ctx) file, err := os.Open(image) userName := "tester" fileName := "test.jpg" mimeType := "image/jpeg" filePath := fmt.Sprintf("%s/%s", userName, fileName) blobWriter := client.Bucket(Bucket).Object(filePath).NewWriter(ctx) blobWriter.ContentType = mimeType io.Copy(blobWriter, file) err = blobWriter.Close() blobPath := fmt.Sprintf("/gs/%s/%s", Bucket, filePath) blobKey, err := blobstore.BlobKeyForFile(ctx, blobPath) // crop opts := image.ServingURLOptions{Secure: false, Crop: true} url, err := image.ServingURL(ctx, blobKey, &opts) log.Infof(ctx, "url", url) return url.String(), err } func TestUpload(t *testing.T) { inst, err := aetest.NewInstance(nil) req, err := inst.NewRequest("GET", "/gophers", nil) url, err := Upload(req) fmt.Printf("test", url, err) }
ローカルで実行すると画像は正常にアップロードされますが、ServingURLがうまく働いてくれないようでhttp://localhost/_ah/img/encoded_gs_file:...
のようなパスになってしまいます。
GAE上だと正常に動いているのですがテストを書く上でとても不便ですね。。