Heroku via Dropbox; Part 2

HerokuのDropbox Syncが終了するとのこと。おせわになりました。

devcenter.heroku.com

Support for Dropbox Sync will end on 24 July 2018.


前回からの続き

Heroku via Dropbox - sugilogのブログ

やること

手順

好きなテンプレートを探す。

たとえば、Start Bootstrapで探してみる。

今回は、ここのGrayscaleなテンプレートを使います。(Download!)

ファイル設置

ダウンロードして展開したファイルの中身をDropboxディレクトリ(Herokuのサイト向けのディレクトリ)につっこむ。

lessとか本当はいらないけど、とりあえずは細かいことは気にしない。

f:id:sugilog:20150211232022p:plain

デプロイ

Herokuの管理画面からデプロイ!

f:id:sugilog:20150211232100p:plain

確認してみます。

f:id:sugilog:20150211232125p:plain

↓↓↓

f:id:sugilog:20150211232445p:plain

うまくいかない場合

デプロイして、失敗する時がある。

  • 今やっている方法だと、Herokuにphpで書かれたアプリケーションとして認識されているのだけど、phpファイルが無いと思われる(らしい)。
  • そういうときは、phpファイルに空文字を足すとかして編集保存して、わざと変更があった状態にしておくと、うまくいくかもしれない。

f:id:sugilog:20150211232353p:plain

Heroku via Dropbox

HerokuのDropbox Syncが終了するとのこと。おせわになりました。

devcenter.heroku.com

Support for Dropbox Sync will end on 24 July 2018.


Herokuのデプロイ方法に、Dropbox Syncが追加されていたらしいので、試してみる。

とりあえず、できるだけ簡単に、HTMLを設置して表示することを目指す。

前提

  • Dropboxアカウントを持っている。
    • なければ作ってください。
  • Herokuアカウントを持っている。
    • なければ作ってください。
  • なんか、シングルページのHTMLで、何かしら公開したい人。
    • プログラムを組む気はないし、Facebookとかで公開してればいいし、ぐらいな人。
  • HTMLを少しいじれる人。

Gitを使わなくて良くなるので、簡単なことはHerokuで、無料でできちゃう、とか思ってます。

手順

Herokuで新しくAppを作成する。

App = 新しいサイト、ということで、まずは設置場所をつくる。

ログインをして

f:id:sugilog:20150211192538p:plain

右上の「+」のリンクをクリックして

f:id:sugilog:20150211192548p:plain

Appの名前(サイト名っぽいのん)を入力する。

ここで入力した内容は、デフォルトでのサブドメインになる。

Dropboxと連携する。

予め連携したいDropboxのウェブサイトにログインしておくと良いです。

「Deploy」タブで「Dropbox」を選んで

f:id:sugilog:20150211192554p:plain

「Connect to Dropbox」な感じで進んで

f:id:sugilog:20150211192546p:plain

連携を承認して

f:id:sugilog:20150211192555p:plain

おわりです。

Dropboxをみると、Dropbox > Apps > Heroku > (入力したApp名)ディレクトリが作られる。

f:id:sugilog:20150211192545p:plain

ファイル設置

ここだけ、自分のパソコンで作業。

f:id:sugilog:20150211192551p:plain

ここでは、index.htmlindex.phpの2つのファイルを設定してみます。 Dropbox > Apps > Heroku > (入力したApp名)ディレクトリの下に置く感じ。

HerokuにDropbox経由でStaticなファイルを設置してみる

デプロイ

HerokuのDropbox Syncは自動的にデプロイされるわけではないので、Herokuの管理画面から作業が必要です。

  • おかげで、Dropboxにファイルを設置したまま、作業ができて便利。

「Deploy」タブの「Dropbox」から

f:id:sugilog:20150211192549p:plain

「Deploy Changes」のメッセージに変更内容の要約を入力して

f:id:sugilog:20150211192552p:plain

「Deploy」押して、少し待つと完了。

f:id:sugilog:20150211192543p:plain

表示されました。

Go言語:Channelsのselect

select の話

  • selectステートメントで、複数のChannelsを条件分岐できる。
    • 受信、送信、どちらも可能。
    • Channelsの送信があるのに、受け取りを行ってなかったら、selectをしていない場合と同じで例外になるので注意。
    • 複数条件に一致する場合は、ランダムに選択される。
  • selectの中のいずれにも該当しない場合の条件をdefaultで指定可能。
    • Channelsに限定した話ではない。注意。

試してみた

Channelsのselect

実行結果

start? 1
0 0
1 1
2 1
3 2
4 3
5 5
6 8
7 13
8 21
9 34
10 55
11 89
12 144
13 233
14 377
15 610
16 987
17 1597
18 2584
19 4181
quit
0 0
1 1
2 1
3 2
4 3
5 5
6 8
7 13
8 21
9 34
10 55
11 89
12 144
13 233
14 377
15 610
16 987
17 1597
18 2584
19 4181
quit

コード中のコメントアウトしているdefault内の行を解くと、演算実行の間(繰り返されている間)に、何度もdefaultが呼び出されていることがわかる。

Go言語:数値型の幅

フィボナッチなサンプルを写経して動かしていた時にやっと理解した。

Go言語の数値型(の整数)

  • intはジェネリックであり、実行環境に依存したサイズ(値の扱える範囲)を持つ。
  • 範囲を超えた場合は、オーバーフローを起こす。
    • 数値演算を行った結果、扱える範囲の最小または最大を超える。
  • オーバーフローが発生しても例外は発生しない。
    • ただし、リテラルの場合は、例外が発生する。
    • わかりきったオーバーフローのためと推測。
  • オーバーフローしたら破棄され、ラップアラウンドが発生する。
    • 扱える範囲の最大値に達した後に、最小値に戻る。
    • 扱える範囲の最小値に達した後に、最大値に戻る。
  • ラップアラウンドが発生するため、x < x + 1が常に成り立つとは限らない。

  • ラップアラウンドを発生させる使用であるため、暗黙的な型変換は発生しない。

なぜGoには暗黙的な数値変換がないのですか?

C言語における数値型での自動型変換の利便性は過剰であり、混乱を招く原因となっています。式が符号無しなのはいつか? 値の大きさはどの位? オーバーフローする? 型変換の結果はポータブルで実行されるマシンに非依存? これはコンパイラも複雑にします。「通常の算術変換」の実装は簡単ではなく、アーキテクチャ間で一貫性を保つことも簡単ではありません。私たちは移植性の理由から、コード中で明示的に型変換をする労力を払うことによって、明確で解り易くする決断をしました。それでも、Go言語での定数の定義(符号およびサイズのアノテーションの要らない任意精度の値)は問題をかなり改善しています。

これと関連しますが、C言語とは違い、仮にintが64ビットだったとしても、intとint64は明確に別の型となります。int型はジェネリックです。整数が何ビットあるのかを気にしたい場合、Go言語では明示的に指定することが推奨されます。

引用:プログラミング言語Goドキュメント 言語設計

試してみる

実行環境は64bitマシン

整数のオーバーフローとラップアラウンド

実行結果

overflowIntWithLiteral
9223372036854775807 + 0 => 9223372036854775807
overflowInt
9223372036854775807 + 0 => 9223372036854775807
9223372036854775807 + 1 => 9223372036854775806
overflowUint8Max
255 + 0 => 255
255 + 1 => 254
overflowUint8Min
0 - 0 => 0
0 - 1 => 255

コード中のコメントアウトを解いて実行すると、

# command-line-arguments
./overflow.go:21: constant 9223372036854775808 overflows int

Rubyで慣れきってて、めちゃくちゃに大きい数値を扱うことが少ないと、下手にラップアラウンドを罠として踏みそう。

大事なのは、明示的にプログラミングすることと、そのための想定。

Go言語:Channesの制限

Channelsの話

  • Channelsはバッファにすることができる。
    • 容量を指定することが可能。
    • make関数の第2引数に指定。
  • caplenの実行が可能。
    • 容量cap以上にはバッファ(値の送信)できない。ブロックする。
    • バッファサイズlen以上には取り出し(値の受信)できない。
  • 送信する値がなくなったら、Channelsを閉じることができる。
    • 受信側で閉じない。
    • 閉じることは必須ではない。
  • Channelsの受け取り側で、閉じられているかどうかがわかる。
    • 受信のチャネルオペレータの2番目のパラメータ(boolean)がcloseかどうかがわかる。
    • 閉じられている場合、バッファサイズ以上の取り出し(値の受信)が可能。
    • 受信される値は型のデフォルト値(だと思う)。intなら0。
  • rangeで受信すると、閉じられるまで繰り返される。
    • rangeを使う場合は、必ず閉じなければいけない。
    • 実行時エラーになる。

書いてみた1

バッファ

出力

before send
0
2
after send
2
2
received value
1
2
after receive
0
2

コメントアウトを解いてみると、fatal errorが発生する。

  • 容量以上に送信しようとした時。
  • バッファサイズ以上に受信しようとした時。
  • コンパイル時にエラーにはならないため、実行時エラーとなる。
  • エラーの内容から、送信か受信かがわかる。
all goroutines are asleep - deadlock!

goroutine N [chan send]:
fatal error: all goroutines are asleep - deadlock!

goroutine N [chan receive]:

書いてみた2

Channelsのcloseとrange

range

0
1
1
2
3
5
8
13
21
34

rangeじゃない

0 true
1 true
1 true
2 true
3 true
5 true
8 true
13 true
21 true
34 true
0 false

rangeでcloseしなかった場合。

  • 実行時エラーで以下のようなエラーが出る。
  • エラーするのは、rangeの行。
fatal error: all goroutines are asleep - deadlock!

goroutine N [chan receive]:

rangeを使わない受信でcloseしなかった場合。

  • 書いてみた1で記述したとおり、実行時エラーする。

Go言語:Goroutines

Goroutinesの話

goroutine (ゴルーチン)は、Goのランタイムに管理される軽量なスレッドです。

  • go 関数呼び出しで新しいスレッドで処理される。
    • プログラムは、スレッドの処理の終了を待つわけではない。
    • 新しいスレッドで処理が始まるのに(ノンブロックの状態で)遅延がある。
  • Channelsを使うと、簡単に同期的な処理が書ける。
    • 条件を明示せずに、同期を許可する、ということらしい。
    • Channelsの操作には、channel operator <-を用いる。
    • channel <- x でChannelsに値を送信、y := <- channelで受信し変数へ値を割り当てる。
  • Channelsの生成には、makeを用いる。
    • make( chan 型 )
    • 型以外の値を送信しようとすると、cannot use xxx (type xxxの型) as type 正しい型 in sendとしてコンパイルに失敗する。

書いてみる1

Goroutines:ベーシック

sample.goの出力

  • goroutineでの処理が遅れて実行される。
  • goroutineでない処理とは並行して処理が進む。
0 second
0 first
1 second
1 first
2 second
2 first
3 second
3 first
4 second
4 first

sample.nooutput.goの出力

  • なにも出力されない。
    • プログラムのほうが早く終了する、という理解で合ってる?

sample.sleep.goの出力

  • goの呼び出しの後にsleepを入れた。
  • goroutineでの処理が先に実行される。
    • たまたま、1ミリ秒以内でgoroutineの処理が先に始まった、という方が正しいかもだが。
0 first
0 second
1 first
1 second
2 first
2 second
3 first
3 second
4 first
4 second

書いてみる2

Goroutines:ポインタ

ポインタはgoroutineでないときと同じように振る舞うらしい。

出力

1 0 1
2 0 2
3 0 1
1 1 3
2 1 4
3 1 2
1 2 5
2 2 6
3 2 3
1 3 7
2 3 8
3 3 4
1 4 9
2 4 10
3 4 5
10

書いてみる3

  • ポインタで書くより明らかにわかりやすい。
  • 同期したいタイミングが明示できる。

Goroutines:Channels

invoke Channel A
1 0 1
2 0 2
1 1 2
2 1 4
1 2 3
2 2 6
1 3 4
2 3 8
1 4 5
2 4 10
5 10
invoke Channel B
3 0 3
3 1 6
3 2 9
3 3 12
3 4 15
4 0 4
4 1 8
4 2 12
4 3 16
4 4 20
15 20

Go言語:HTTPサーバーのコーディングをしてみる

↓のslideshareのコードを写経していく。

写経させていただきました。資料ありがとうございます!

とりあえずコーディング

HTTPサーバーの写経// http://www.slideshare.net/yasi_life/ ...

構成

  • GOPATH/src/server.go
    • サーバープログラム
  • GOPATH/views/view.html
    • 表示画面のテンプレート
  • GOPATH/views/edit.html
    • 編集画面のテンプレート

まだやっていないこと

  • セキュリティとか、全然考えてない。
  • セッションも何もない。
    • 相対パスでアクセスしているので、プログラムと関係ない変なファイルにアクセスできるかもしれない。
    • とか。
  • 保存失敗した時の処理をしていない。
    • 名前に/が含まれている場合に、このコードだとno such file or directoryが出る。
    • でもそのメッセージをユーザーに返していない。

思ったこと

  • 簡単なレベルの実装であれば、すごい簡単。
    • 提供されているパッケージが充実している印象。
  • ルーティングに関数を渡すのは読みやすい。
    • JavaScript勉強していた人がGo言語やるとか、いいかも。
    • JavaScriptでイベントドリブンな実装を中心にやっていた人が、か。